This week marks the 20th Anniversary of the Hague Appeal for Peace.
This week marks the 20th anniversary of the Hague Appeal for Peace and everything that happened (and didn’t) as part of that event and since, I decided to post some of my pictures from that adventure.
In my post on being an activist back in March I mentioned attending the Hague Appeal and the peace walk that followed. I was part of a delegation from Philadelphia Yearly Meeting; a group mostly made up of college students and a few older high school students, along with a few adults who handled the logistics and kept us on track more or less.
I have ten boxes of slides, and a few years ago I scanned them as best I could but frankly the scans aren’t great. The slides, which were more than ten years old at the time, had already started to fade and color shift as a result of their age. I did some color correction as I prepped them for this, but I also like the feel of some being somewhat faded and shifted with time. There are shared here full frame, and some are roughly cropped, but none carefully realigned. Since they are now pushing twenty I decided that I wanted to leave them all at or near full size and try to capture a bit of the way I saw the world then, and less of how I would edit it now. I like the rough visual feel they have as part of reflected on partially faded memories.
That trip was an important few weeks in my life, and I’ve been having a great time going back through the pictures. If you were with me on that trip and wonder if I have other pictures of you kicking around I might so send me a note and I’ll try to see what’s around and sent some your way.
For a project I’ve been working on recently we had need to create a module that provides secure redirects from a Drupal site to FormAssembly. Overall the module does a number of things, but handling dynamic parameter signing was the thing that took the most time.
FormAssembly provides a variety of great features for creating flexible forms that integrate with Salesforce. One of the more popular features is its ability to pull data from Salesforce to prefill fields on a form. But the downside is that it is easy to create forms that leak information from Salesforce into those forms, and create privacy risks.
To address this, FormAssembly allows 3rd party tools to securely sign URLs that contain parameters (often Salesforce IDs) that could be used to extract information through an iteration attack and other basic approaches. This secure signing process can be done statically but for most interesting projects you want to sign the URLs dynamically. The dynamic signing process allows you alter the parameters on the fly and set an expiration date to limit the value of a stolen link. Our project required this approach.
But the dynamic signing process has a couple sharp corners. First, it’s rarely done outside of Salesforce so there aren’t a lot of code samples around, and none that I could find in PHP. Second, FormAssembly is very open and honest about the fact that they do not provide support on this feature. So I had to create my own process from the documentation they provide. The docs are good, but very Salesforce centric, with all code samples in APEX.
The process involves preparing the data for signature, generating a HMAC-SHA256 with a form specific pre-shared key (in binary mode), converted to a string using base64, and finally URL encode the result.
Their convention for preparing the data is straightforward. You format all parameters as just their key and value strung together: key1Value1key2Value2
The interesting part is the actual HMAC-SHA256, which needs to be generated in binary mode, something that is often the default mode but not in PHP (in fact most PHP devs I’ve talked don’t realize the last parameter to hash_hmac() is useful, if you are doing this in another language check out this collection of examples).
From there you encode the output in base-64 (which results in a 44 character hash), and URL encode the hash to make sure it’s URL safe, and you’ll end up a few characters longer.
Finally you add you hash to the query string, and you’re ready to go.
To help anyone else who needs to do this, I generalized this part of the solution and I created and tossed it into Gist.
When someone tries to insult you with what you often see as a compliment it is worth stopping to reflect. Am I an activist? If I’m not, should I be?
On Valentines Day this year my wife and I spent a few hours at DSS for a meeting related to some of the children we work with in the Guardian ad Litem program. In the course of a rather tense conversation a caseworker tossed out “Well, I am not an activist.” with the clear intention of implying that I am, and that activists are a problem.
It is the first time I can recall being called an Activist as an insult, and I’ve been a bit hung up on the topic ever since.
At AFSC I had colleagues who would argue if you haven’t been arrested for a cause you aren’t really an activist. We had critics who argued that because AFSC staff were paid they couldn’t be true activists. I didn’t then, nor now, fully agree with those arguments, but my point is that when someone calls me an “activist” those are the comparisons they are drawing in my mind.
My credentials as an activist on that scale are weak at best. The first time I spent a lot of time with activists was in 1999 during the Hague Appeal for Peace and a peace walk that followed. The group walked from the Peace Palace – home of the international criminal court – in The Hague, Netherlands to Nato Headquarters in Brussels, Belgium. That picture of the water cannon firing on a crowd at the top of the page is mine, although I wasn’t willing to risk arrest that day (my sister was getting married the next week and my mother would have killed me if I’d missed it because I had been arrested in Europe – would a true activist be deterred by such things?).
It was a great experience, but didn’t do a thing toward our goal of nuclear disarmament – I now live in a town supported by nuclear weapons maintenance (and soon pit production too).
After college I took a job at AFSC which consisted of largely back office functions of one type or another – while defining for my career and personally gratifying work there is an important difference between building the tools activists need to communicate and being the activist. In 2008 I was part of planning a peace conference in Philadelphia as part of the Peace and Concerns standing committee, but it is important to note that I objected to the civil disobedience that was part of that event (being a consensus driven process people feared I would block it entirely – but I stood aside so they could move forward).
I’ve been to other events and protests, although sometimes as much accidentally as purposefully. So while the account is not empty, it’s not exactly the kinda stuff that gets you into history books, or even an FBI file worth reading.
Having spent much of my professional life supporting back office functions on nonprofits, and now interacting with DSS as a volunteer who has to be careful about what I share since I have to maintain the privacy of the kids we work with, I struggle to envision myself as an activist. I support activists sure, but I don’t see myself as one.
But when someone tries to insult you with what you often see as a compliment it is worth stopping to reflect. Am I an activist? If I’m not, should I be?
It occurred to me this case worker has a much lower standard of what it means to be an activist than I do – anyone who simply speaks against the status quo in favor of well established laws and precedents are activists in his book. To be fair he’s not far off the suggestion Bayard Rustin, and the committee who helped him write Speak Truth to Power, were making. And as much as I am sure they would deny it, the caseworkers are the most powerful people in the lives of children in foster care: they dictate where the children live, who they can talk to, if/when they see siblings, when they buy clothes, where they go to school, what doctors they see, and without an active advocate they shape how the courts see the children. And right now in South Carolina their power is being tested and reigned in because a group of Guardians ad Litem stood up a few years ago to the rampant systemic abuses.
The ramifications of that class action are still being determined, and no one really knows what the lasting effect will be. But this case worker has inspired me to make sure we honor the sacrifices they made (all were forced to stop fighting for the named children because they were “distractions”).
I’m not sure I am an activist, but I promised those kids I would stay with them until the judge ordered me to stop. No matter what taunting I get from the case workers, their bosses, and others within the power structure I can speak truth to power as long as I must.
For the SC DUG meeting this month Will Jackson from Kanopi Studios gave a talk about using Docksal for local Drupal development. Will has the joy of working with some of the Docksal developers and has become an advocate for the simplicity and power Docksal provides.
We frequently use these presentations to practice new presentations, try out heavily revised versions, and test out new ideas with a friendly audience. If you want to see a polished version checkout our group members’ talks at camps and cons. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback.
If you would like to join us please check out our up coming events on Meetup for meeting times, locations, and connection information.
A few weeks ago I took a few hours to scratch an itch and went out did a little local photography. I spent much of my time wondering the trails through Aiken State Park. Although there are a few included here from another stop I made, and from the Lunar eclipse on January 21st.
Kaylan Wagner – Real world lessons from online games.
This fall the South Carolina Drupal User’s Group started using Zoom are part of all our meetings. Sometimes the technology has worked better than others, but when it works in our favor we are recording the presentations and sharing them when we can.
In November Kaylan Wagner gave a draft talk on using experiences in the world of online gaming to be a better remote team member.
We frequently use these presentations to practice new presentations and test out new ideas. If you want to see a polished version hunt group members out at camps and cons. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback.
If you would like to join us please check out our up coming events on Meetup for meeting times, locations, and connection information.
Chis Zietlow – Using Machine Learning to Improve UX
This fall the South Carolina Drupal User’s Group started using Zoom are part of all our meetings. Sometimes the technology has worked better than others, but when it works in our favor we are recording the presentations and sharing them when we can.
Chris Zietlow presented back in September about using Machine Learning to Improve UX.
We frequently use these presentations to practice new presentations and test out new ideas. If you want to see a polished version hunt group members out at camps and cons. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback.
If you would like to join us please check out our up coming events on Meetup for meeting times, locations, and connection information.
For this month’s South Carolina Drupal User Group I gave a talk about creating Batch Services in Drupal 8. As a quick side note we are trying to include video conference access to all our meetings so please feel free to join us even if you cannot come in person.
Since Drupal 8 was first released I have been frustrated by the fact that Drupal 8 batch jobs were basically untouched from previous versions. There is nothing strictly wrong with that approach, but it has never felt right to me particularly when doing things in a batch job that I might also want to do in another context – that really should be a service and I should write those core jobs first. After several frustrating experiences trying to find a solution I like, I finally created a module that provides an abstract class that can be used to create a service that handles this problem just more elegantly. The project also includes an example module to provide a sample service.
Some of the text in the slides got cut off by the Zoom video window, so I uploaded them to SlideShare as well:
To define a batch you generate an array in a particular format – typically as part of a form submit process – and pass that array to batch_set(). The array defines some basic messages, a list of operations, a function to call when the batch is finished, and optionally a few other details. The minimal array would be something like:
The interesting part should be in that operations array, which is a list of tasks to be run, but getting all your functions setup and the batch array generated can often be its own project.
Each operation is a function that implements callback_batch_operation(), and the data to feed that function. The callbacks are just functions that have a final parameter that is an array reference typically called $context. The function can either perform all the needed work on the provided parameters, or perform part of that work and update the $context['sandbox']['finished'] value to be a number between 0 and 1. Once finished reaches 1 (or isn’t set at the end of the function) batch declares that task complete and moves on to the next one in the queue. Once all tasks are complete it calls the function provided as the finished value of the array that defined the batch.
The finish function implements callback_batch_finish() which means it accepts three parameters: $success, $results, and $operations: $success is true when all tasks completed without error; $results is an array of data you can feed into the $context array during processing; $operations is your operations list again.
Those functions are all expected to be static methods on classes or, more commonly, a function defined in a procedural code block imported from a separate file (which can be provided in the batch array).
My replacement batch service
It’s those blocks of procedural code and classes of nothing but static methods that bug me so much. Admittedly the batch system is convenient and works well enough to handle major tasks for lots of modules. But in Drupal 8 we have a whole suite of services and plugins that are designed to be run in specific contexts that batch does not provide by default. While we can access the Drupal service container and get the objects we need the batch code always feels clunky and out of place within a well structured module or project. What’s more I have often created batches that benefit from having the key tasks be functions of a service not just specific to the batch process.
So after several attempts to force batches and services to play nice together I finally created this module to force a marriage. Even though there are places which required a bit of compromise, but I think I have most of that contained in the abstract class so I don’t have to worry about it on a regular basis. That makes my final code with complex logic and processing far cleaner and easier to maintain.
The Batch Service Interface module provides an interface an an abstract class that implements parts of it: abstract class AbstractBatchService implements BatchServiceInterface. The developer extending that class only needs to define a service that handles generating a list of operations that call local methods of the service and the finish batch function (also as a local method). Nearly everything else is handled by the parent class.
The implementation I provided in the example submodule ends up four simple methods. Even in more complex jobs all the real work could be contained in a method that is isolated from the oddities of batch processing.
<?php
namespace Drupal\batch_example;
use Drupal\node\Entity\Node;
use Drupal\batch_service_interface\AbstractBatchService;
/**
* Class ExampleBatchService logs the name of nodes with id provided on form.
*/
class ExampleBatchService extends AbstractBatchService {
/**
* Must be set in child classes to be the service name so the service can
* bootstrap itself.
*
* @var string
*/
protected static $serviceName = 'batch_example.example_batch';
/**
* Data from the form as needed.
*/
public function generateBatchJob($data) {
$ops = [];
for ($i = 0; $i < $data['message_count']; $i++ ) {
$ops[] = [
'logMessage' => ['MessageIndex' => $i + 1],
];
}
return $this->prepBatchArray($this->t('Logging Messages'), $this->t('Starting Batch Processing'), $ops);
}
public function logMessage($data, &$context) {
$this->logger->info($this->getRandomMessage());
if (!isset($context['results']['message_count'])) {
$context['results']['message_count'] = 0;
}
$context['results']['message_count']++;
}
public function doFinishBatch($success, $results, $operations) {
drupal_set_message($this->t('Logged %count quotes', ['%count' => $results['message_count']]));
}
public function getRandomMessage() {
$messages = [
// list of messages to select from
];
return $messages[array_rand($messages)];
}
}
There is the oddity that you have to tell the service its own name so it can bootstrap itself. If there is a way around that I’d love to know it. But really one have one line of code that’s a bit strange, everything else is now fairly clear call and response.
One of the nice upsides to this solution is you could write tests for the service that look and feel just like any other services tests. The methods could all be called once, and you are not trying to run tests against a procedural code block or a class that is nothing but static methods.
I would love to hear ideas about ways I could make this solution stronger. So please drop me a comment or send me a patch.
Related core efforts
There is an effort to try to do similar things in core, but they look like they have some distance left to travel. Obviously once that work is complete it is likely to be better than what I have created, but in the meantime my service allows for a new level of abstraction without waiting for core’s updates to be complete.
For Christmas this year my wife and I took off and went to Belize. I took some 2,500 pictures and I’m working my way through them. The gallery below will get captions, alt-text, etc soon.
First sighting of Belize on the flight in.
GJ’s Restaurant picked by our driver on the way from Belize City to San Ignacio.
His guy came running when he spotted customers.
We stayed at Midas Resort in San Ignacio, which we’d recommend.
“Husky” the Midas office husky was an important part of our visit.
Midas has two large male green iguanas roaming the property.
Our room at Midas
Midas was also home to several Agouti.
This hand powered ferry coveys everyone going to Xunantunich
The main temple at Xunantunich from the main plaza
This Iguana spends the day watching tourists explore his home on the temple at Xuanatunich
The frieze on the side of the temple (larger version below).
People looking out from the top of the temple
A view from the furthest building at Xunantunich back toward the temple.
A view from Belize from the top of the temple.
The Howler monkeys were yelling from tree tops when we arrived, but quietly feeding later in the morning.
One of the buildings at Cahal Pach in San Ignasio.
The central, but smaller, plaza at Cahal Pach.
My wife walking through one of the passages at Cahal Pach.
Belikin the beer of Belize served in standard style.
The tonic was pink which threw me off at first.
San Ignasio is home of a large and busy open air market.
All the way to Belize to watch my first Sixers game of the year.
The east temple from Complex Q at Tikal.
My wife walking down from the top of the east temple.
The two of us on the steps to the east temple.
First view we got of Temple I
The back of Temple I
The buildings from the main plaza in Tikal.
Temple I from the plaza.
The view from the top of Temple IV in Tikal.
All ships leaving Yavin base pass through this scene.
There were lots of people at the top, and that fence in the background was the only safety rail
The spider monkeys were one of the coolest things we saw.
This guy stopped to watch us for a bit.
He scooped water out of a hole in the and drank upside down.
We got really lucky to see this mother and baby passing by.
This Coati was snuffling in the grass near the visitor center
A green iguana from the rescue program in town.
Another green iguana from the rescue program in town.
The males turn orange to show off.
My wife and I with one of the rescued iguana.
This guy kept his distance and his eyes on us.
The entrance to Barton cave.
The view back out from the Barton creek cave.
The Big Rock Waterfalls in the Pine Mountain reserve.
Butterfly from the San Jose Succotz TrekStop
Butterfly caretaker from the San Jose Succotz TrekStop
Butterfly from the San Jose Succotz TrekStop
We spent Christmas itself in San Pedro
The view from our hotel room in San Pedro
There are some nice views on San Pedro beaches.
They were just enjoying people watching.
This guy sells nice carvings like the ray he’s holding to visitors.
Cause what else would Santa ride on a beach.
There was a party in the town square Christmas morning starting at Midnight. I didn’t stay for much.
Rode bikes out to Secret Beach which is anything but secret.
There are at least two bars at Secret beach
Machete, Coconut, and drinks. What could go wrong (nothing for her).
Took bikes down to Marco Gonzalez Mayan site. The path looked like something from Myst.
Marco Gonzalez is mostly still covered in jungle.
Mayans here used Conch shells to build walls. They are kinda creepy 500 years later.
Beatrice is one of three Black Iguanas with names at Marco Gonzalez
Sun rise from our hotel room.
These panoramic pictures were created with a combination of my iPhone in pano mode and some that are stitched together with Hugin.
Picture of Belize taken from the top of the temple at Xunantunich. Stitched with Hugin.Same angle made with iPhone.Picture of Guatemala from the other side of the temple at Xunantunich stitched with Hugin.Another of Guatemala with the iPhone.The frieze on the side of the temple. This is actually a cast created over the top of the original to protect it from weather.The temple taken from the main plaza.Taken from the side of the temple.The main plaza at Cahal Pech ruins at the edge of San IgnacioThe main plaza at TikalTaken from the top of the observatory at Tikal.Taken from the top of Temple IV at Tikal. Scenes from Yavin base in Star Wars were shot near this spot.Another stitched image from Temple IV.Dock on the beach in San Pedro.A bit north of Secret Beach (which is anything but secret) we found a nice dock to enjoy our lunch.
In software just about all project management methodologies get labeled one of two things: Agile or Waterfall. There are formal definitions of both labels, but in practice few companies stick to those definitions particularly in the world of consulting. For people who really care about such things, there are actually many more methodologies out there but largely for marketing reasons we call any process that’s linear in nature Waterfall, and any that is iterative we call Agile.
Failure within project teams leading to disasters is so common and basic that not only is there a cartoon about it but there is a web site dedicated to generating your own versions of that cartoon (http://projectcartoon.com/).
Among consultants I have rarely seen a company that is truly 100% agile or 100% waterfall. In fact I’ve rarely seen a shop that’s close enough to the formal structures of those methodologies to really accurately claim to be one or the other. Nearly all consultancies are some kind of blent of a linear process with stages (sometimes called “a waterfall phase” or “a planning phase”) followed by an iterative process with lots of non-developer input into partially completed features (often called an “agile phase” or “build phase”). Depending on the agency they might cut up the planning into the start of each sprint or they might move it all to the beginning as a separate project phase. Done well it can allow you to merge the highly complex needs of an organization with the predefined structures of an existing platform. Done poorly it can it look like you tried to force a square peg into a round hole. You can see evidence of this around the internet in the articles trying to help you pick a methodology and in the variations on Agile that have been attempted to try to adapt the process to the reality many consultants face.
In 2001 the Agile Manifesto changed how we talk about project management. It challenged standing doctrine about how software development should be done and moved away from trying to mirror manufacturing processes. As the methodology around agile evolved, and proved itself impressively effective for certain projects, it drew adherents and advocates who preach Agile and Scrum structures as rigid rules to be followed. Meanwhile older project methodologies were largely relabeled “Waterfall” and dragged through the mud as out of date and likely to lead to project failure.
But after all this time Agile hasn’t actually won as the only truly useful process because it doesn’t actually work for all projects and all project teams. Particularly among consulting agencies that work on complex platforms like Drupal and Salesforce, you find that regardless of the label the company uses they probably have a mix linear planning with iterative development – or they fail a lot.
Agile works best when you start from scratch and you have a talented team trying to solve a unique problem. Anytime you are building on a mature software platform you are at least a few hundred thousand hours into development before you have your first meeting. These platforms have large feature sets that deliver lots of the functionality needed for most projects just through careful planning and basic configuration – that’s the whole point of using them. So on any enterprise scale data system you have to do a great deal of planning before you start creating the finished product.
If you don’t plan ahead enough to have a generalized, but complete, picture of what you’re building you will discover very large gaps after far too many pieces have been built to elegantly close them, or your solution will have been built far more generically than needed – introducing significant complexity for very little gain. I’ve seen people re-implement features of Drupal within other features of Drupal just to deal with changing requirements or because a major feature was skipped in planning. So those early planning stages are important, but they also need to leave space for new insights into how best to meet the client’s need and discovery of true errors after the planning stage is complete.
Once you have a good plan the team can start to build. But you cannot simply hand a developer the design and say “do this” because your “this” is only as perfect as you are and your plan does not cover all the details. The developer will see things missed during planning, or have questions that everyone else knows but you didn’t think to write down (and if you wrote down every answer to every possible question, you wrote a document no one bothered to actually read). The team needs to implement part of the solution, check with the client to make sure it’s right, adjust to mistakes, and repeat – a very agile-like process that makes waterfall purists uncomfortable because it means the plan they are working from will change.
In all this you also have a client to keep happy and help make successful – that’s why they hired someone in the first place. Giving them a plan that shows you know what they want they are reassured early in the project that you share their vision for a final solution. Being able to see that plan come together while giving chances to refine the details allows you to deliver the best product you are able.
Agile was supposed to fix all our problems, but didn’t. The methodologies used before were supposed to prevent all the problems that agile was trying to fix, but didn’t. But using waterfall-like planning at the start of your project with agile-ish implementation you can combine the best of both approaches giving you the best chances for success. We all do it, it is about time we all admit it is what we do.