Emily Stamey

Developer & Human. Finding my voice.

Delivering “Hey Boss…” at Explore DDD

In September, I traveled to Denver to speak at Explore DDD, a fantastic conference! When I first read their mission, I was excited to attend and hopeful my talk would be selected. Their focuses were practicality, collaboration, and learning. The conference and its attendees truly delivered on these values! I thoroughly enjoyed this conference and learned so much. I hope to return there to learn even more next year!

Below is the recording of my talk, which was aimed at beginners who may be wondering how they could use Event Sourcing in their applications. Next year, I am excited to be giving a similar talk that will spend a little less time on the introductory concepts and will dive deeper into how these projects used Event Sourcing. You can catch that talk at DDD Europe in February, 2020.

Emily Stamey presents “Hey Boss, Event Sourcing Could Fix That!” at Explore DDD in Denver

Staying local for a bit

Hi, I’m working toward a better blogging habit, but in the meantime I’m staying close to home, studying a few things, finishing some unfinished projects, and enjoying my local developer community.  If you would like me to speak at your event, please let me know.  I may be able to fit it in.  For the moment, I’m not seeking CFP to submit my talks to.

Crafty Circuits

On Dec 18th, Women Who Code, Raleigh-Durham had a wonderful meetup!  With kits

from AdaFruit we sewed LEDs to a battery pack and onto a fabric item of our own making.  It was really fun!  Few of us had made anything like this before.  We all had different crafting backgrounds and skill levels.  We helped and encouraged each other, and each of us made something unique.  We talked about other things we enjoy making, and hopefully that will yield more maker activities for Women Who Code!  It was truly a lot of fun!

 

Workshop: Delivering the Most Valuable Features

about 15 people standing around a table that shows the story board for the mock project created by one of the three teams.

The groups share their story boards and plans for future work

On Tuesday at PHP[tek] Workshop Day, I had the pleasure of delivering my first workshop to a group of about 15 people. The workshop is titled Delivering the Most Valuable Features, and we discussed how to use User Story Mapping as a communication and planning tool on our projects. I have learned a lot from this strategy and hope to use it in future work. The group was really fun to work with, and came up with great ideas for project work, and used those ideas to plan future work, tying it to the primary goals of the team. I’m looking forward to giving this workshop at Dutch PHP Conference in Amsterdam on June 29th.

Speaking at OSCON

Emily speaking at OSCON

Last week I traveled to Austin, Texas and the O’reilly Open Source Conference to share a talk called What’s Your Skateboard?  This is a talk I enjoy sharing.  It gives strategies for organizing and planning work.  I started out talking so quickly that I tripped over my tongue a bit.  I got it under control and conveyed the useful strategies to my audience.  In another week, I’ll be giving this in a workshop format at PHP[tek], and I’m really excited about that!  A 40 minute time slot, such as at OSCON, doesn’t leave attendees time to try it out.  The practice will become a lot more clear when attendees can get their hands on some post-it notes and organize work.

In June, I will be giving this talk again at We Rise, and I will give both the talk and the workshop at Dutch PHP.  After that things will settle back down for me with travel and speaking.

Women Who Code Launches in Raleigh-Durham

On Wednesday, April 26th, we began building our community of Women Who Code in the Raleigh-Durham area!

Marjorie Sample, Ruth Suehle, Jelissa Thomas, Jennifer Houchins talk about how they balance the demands of work and their many varied interests.

I have been a programmer for such a long time, and I have never worked on a team with another woman coding on the same project.  I have worked with some really amazing technical women, but I have often felt really alone on my teams as the only woman.  We have a huge technology scene here in RTP, and I know there are many brilliant women out there, so I’m really excited to begin meeting them as we begin having meetings, presentations, and Social Code events in our area.  I’m so unbelievably proud of the team of Directors I am a member of and the greater Women Who Code network.  We will be supporting the Women Who Code in our area and supporting each other!

An Example of Event Sourcing

I’ve been working on a new talk to describe a project where we are replacing an application that used a complex list of statuses to describe where a student’s enrollment request is in the process.  Examining older applications like this one, you easily see how they closely mimicked the old paper form processes.  The status of the paper form was directly tied to its being added to a stack of papers.  Over time, the approval process became more complex, and the number of piles or statuses increased.  The status drop-down in this application became REALLY long!  Before we begin examining a lot of statuses, I’d like to discuss the simple example.  After a Student submits their Enrollment Request, an Admin either Approves or Rejects their Request.

Bounded Contexts

Our team has built applications using DDD.  We recognize the bounded contexts of Student and Admin spaces in the code as well as in the user interfaces.  Without making this overly complicated, we know that there are some actions a Student makes in this system and at a point, they are just waiting to hear back from the Admin.  There are a completely different set of things the Admin does in this space.  When we create a bounded context, we let the code mirror their real-life processes, without muddying the concerns of the other bounded context.  There is no scenario where a Student can Approve or Reject an Enrollment Request, so we will begin there.

Events to Approve and Reject an Enrollment

A diagram showing a form arrives and is either approved or rejected

A student Submits an Enrollment Request and then waits to hear what has happened to it.  The Admin may request more information from the Student before they can approve or reject.  But on a very basic example, the student submits an Enrollment Request and waits for a notice of Approve or Reject.  The Approve or Reject Events will trigger a message to the student and probably some other things.  Our Admin receives the request and clicks a button, either Approve or Reject.  When they click, a corresponding event is created.  The event is a class like this:

public class EnrollmentRequestApproved implements Event
{
    // @var UUid
    public $enrollmentRequestId;

    // @var StudentId
    public $studentId;

    // @var CourseOfferingId
    public $courseOfferingId;

    public function __construct(Uuid $enrollmentRequestId, StudentId $studentId, CourseOfferingId $courseOfferingId)
    {

        $this->enrollmentRequestId = $enrollmentRequestId;
        $this->studentId = $studentId;
        $this->courseOfferingId = $courseOfferingId;
    }
}

All Events are stored in an Event Store, and they are stored in the order they are recorded.  We can listen for Events arriving in the Event Store, and trigger certain things to happen based on those Events.  Let’s say the Admin wants a list of all Enrollment Requests that haven’t been Approved or Rejected, so they can enroll the students in classes they need.  We’ll call this Enrollment Request Projector.  It will maintain a list of all Enrollment Requests.  When a student submits their request for enrollment, our Projector will add it to the list of Enrollment Requests.

The Admin Dashboard will display all requests in this table. The beforeReplay() and afterReplay() methods allow us to easily rebuild the Projection based on new information.  The apply… methods contain the changes that are made to the table based on the Event.A new StudentRequestedEnrollment event will add a Enrollment Request with a status of “requested”.  But when the admin approves or rejects the request, that corresponding Event will be created.  When our Projector detects the Approve or Reject event, the corresponding Enrollment Request will be removed from the table.

class EnrollmentRequestProjector extends SimpleProjector implements Replayable
{

    /**
     * @var Connection
     */
    private $connection;

    /**
     * @var string table we're playing events into
     */
    private $table = 'proj_enrollment_requests';

    public function __construct(Connection $connection)
    {
        $this->connection = $connection;
    }

    public function beforeReplay()
    {
        $builder = $this->connection->getSchemaBuilder();

        $builder->dropIfExists('proj_enrollment_requests_tmp');
        $builder->create('proj_enrollment_requests_tmp', function (Blueprint $schema) {
            $schema->string('id');
            $schema->string('student_id');
            $schema->string('course_offering_id');
            $schema->string('status');

            $schema->primary('id');
        });

        $this->table = 'proj_enrollment_requests_tmp';

    }

    public function afterReplay()
    {
        $builder = $this->connection->getSchemaBuilder();

        $builder->dropIfExists('proj_enrollment_requests');
        $builder->rename('proj_enrollment_requests_tmp', 'proj_enrollment_requests');

        $this->table = 'proj_enrollment_requests';
    }

    /**
     * @param StudentRequestedEnrollment $event
     */
    public function applyStudentRequestedEnrollment(StudentRequestedEnrollment $event)
    {
        $enrollmentRequest = new EnrollmentRequest;
        $enrollmentRequest->setTable($this->table);

        $enrollmentRequest->id = $event->enrollmentRequestId->toString();
        $enrollmentRequest->student_id = $event->studentId->toNative();
        $enrollmentRequest->course_offering_id = $event->courseOfferingId->toNative();
        $enrollmentRequest->status = 'requested';

        $enrollmentRequest->save();
    }

     /**
     * @param EnrollmentRequestApproved $event
     */
    public function applyEnrollmentRequestApproved(EnrollmentRequestApproved $event)
    {
        $enrollmentRequest = EnrollmentRequest::where('id',  $event->enrollmentRequestId->toString())
        $enrollmentRequest->delete(); 
    }


     /**
     * @param EnrollmentRequestRejected $event
     */
    public function applyEnrollmentRequestRejected(EnrollmentRequestRejected $event)
    {
        $enrollmentRequest = EnrollmentRequest::where('id',  $event->enrollmentRequestId->toString())
        $enrollmentRequest->delete(); 
    }
}

This is a long piece of code to review.  But I hope that it will demonstrate how the events work.  I am still doing quite a bit of hand-waving around the event store and some of our classes that we are using in this project.  I apologize for that.  The part I want you to understand, the useful take-away is that these events can be applied in different contexts of the application.  For the Admin Dashboard, the EnrollmentRequestRejected and EnrollmentRequestApproved has one effect on the Enrollment Request projection.  But if we wanted a view of the Closed Enrollment Requests, we could apply those same events in an opposite way.  Likewise, the Student Dashboard has its own sets of methods that apply the events that are relevant.  From this context, the events are applied differently.  A Student wants to see the status of their requests, and their aim is to be Enrolled, which is actually a step beyond Approved.  An Event tied to the Registration System will let us know that they are enrolled in the course, and completes this part of the example.

 

 

 

 

 

Crocheting Through Love and Loss and My Long Absence

This isn’t a technical share; it’s a lot more feelings-based.  And I know some of my community posts are feelings based, but this one is different.  Last year I lost a bunch of people in a relatively short amount of time.

In the Spring, I was supposed to see my friend in Chicago after a conference, but she’d just gotten bad news that the cancer she’d been fighting for nearly two years had not only spread, but was inoperable.  I didn’t get to see her, but she did come to visit on her way to the beach.  It was stressful and hard to visit with our kids in moods, but I was so grateful to see her for even a short time!

At the end of the Summer, my Step-Grandmother had some medical issues, then an infection, and next thing we knew she was in hospice. I met her when I was maybe 11.  She and my Grandmother were close friends.  They took me to the zoo.  Maybe 10 years later, my parents had divorced and I was now her family member by marriage.  It’s odd becoming a step-child as an adult.  It’s complicated, and there are still a lot of hurt feelings about things that were said to me and ways that I was treated by some members of my new family.  But my step-grandmother, who had known me longer than I remembered knowing her, was always so welcoming and kind to me.  She never made me feel like a disappointment, an “other”, or someone who didn’t belong.  She was wonderful!!!

Around the time I was getting married, we spent a lot of time talking, and she

Mandala Madness Afghan - part5

Mandala Madness Afghan – part5

shared so much advice and stories with me.  I loved hearing about her life.  And sometimes she would tell me about my grandmother who I died before I  was an adult. She was a really fabulous person!  I felt a great loss when she died.  I’ll always remember her for never making me doubt my belonging!  When I first heard that she had died(from a step-cousin who posted it on Facebook),  I was pretty upset.  I remember that when I was processing that grief, I discovered a mistake early in the green section and had to remove the whole thing.  I cried the whole time, thinking of her, not the lost work.  It was the first part of this project that had really been associated with something sad, but I still think of that green section as healing.

 

Violet Femme

Shortly after that, a roller derby league-mate (who had been wonderful to me when I was a Carolina Rollergirl) died suddenly and tragically.  It was hard to learn that she had been having a hard time in her life.  It was hard to feel so many what-ifs and to mourn the lost time and opportunity to see her skating and so full of life and spirit.  We were all shaken by the loss of Violet, but the funeral was a very loving send-off, and .  Throughout the funeral and wake, I kept thinking about the coming loss of Mel, who was going into hospice.  Mel and Violet were both Carolina Rollergirls.

 

Mandala Violets

Mandala Violets

Soon after I was working on these little flowers in the piece, and it felt connected to Violet.  So much of this afghan felt connected to all of the loss I was feeling.  I was still working on these flowers when I arrived in Illinois to be with Mel for a week or two.  I was crocheting them as I talked to Mel about Violet’s funeral.  I sat with Mel when she slept because she would get scared when she woke up alone.  It was hard to be there, but it had been harder to not be there, to be unable to help before.  So I sat with her and ran errands.  I played with her kids, so her husband could sit with her.  It was so hard!  Her kids were so young (2, 4, and 6) and had no idea what was happening.  They we so cute and sweet and so loud as small kids are.  I talked with Mel, and I rubbed her legs if her pain was managed enough.  I helped her place an order of books for the kids’ Christmas gifts.  It was one of the last things I was able to help with before I went home.

Emily and Mel

I went home just before Thanksgiving, and I was super depressed.  I felt guilty that I was able to have a Thanksgiving with my family while they were suffering.  Mel wasn’t eating much food when I left, so I knew she wouldn’t be eating turkey. I received a few messages from her and then it was just me checking on her husband.  I was mostly reaching out, letting him know I knew it sucked and kindof throwing a signal that he wasn’t alone, even though he was. He was caring for three kids and his dying wife.  It was horrible!

 

Mandala Madness Part 11December 18th, I received a message that Mel had died. Our mutual friends and her family, we were all wrecked.  It was so unbelievable and unfair.  A few days before Christmas about 120 pounds of books were delivered to her kids.  As part of the book list we compiled before I left, these books had been bought by her friends from all over the country, and sent as a loving gift from their mother.  It was so rewarding to know that I could help her give that to them.  It was a difficult task to complete at the time.

So last year was kindof rough, and I can’t even say for sure that I’m over it.  But tonight it felt super important to just write this down to acknowledge how awful last year was.  To document the ways that my working on this afghan has been so closely tied to major life events before I forget them.  I shared a lot of this unabashedly with friends because there was so much grief and nowhere for me to keep it.  I had a lot of wonderful friends support me.  Some people who barely knew me offered support to me, and I’m forever grateful to them.  It helped so much to have this groups of friends who had few or no connections to the people I had lost. I could share their stories and my feelings without burdening others who were also grieving.  I don’t think I could have been as good a friend to Mel if I hadn’t had them to virtually hug and cry to in the evenings when it all hit me.

 

 

What Community Means to Me

Ever since I began attending conferences again, there have been several things bugging me.  Primarily it’s that so little has changed since I started college and later attended my first conference in 2001.  I ALWAYS bristled when a speaker would give a long list of their fellow speaker friends held up as community leaders.  There is no way to list every speaker in that list, so it seemed to focus on that person’s friends.  I knew the omitted speakers would feel left out, but I also thought about everyone else in the room who was definitely a member of the community who could feel left out in this type of talk.  It’s taken me a while to put my finger on this, so please bear with me as I tease this idea out.

When did I join the PHP community?

Well, I learned PHP in 1999.  I was a webmaster for a department on campus.  The IT lead, Kevin, said I needed to learn PHP because it was really cool!  It was, and in 2000 I took my first full-time job using PHP to do super cool things on the Internet.  I would say that I became a member of the PHP community when I first took the Webmonkey tutorial and began asking questions and building tools on the Internet.

At conferences, there is this idea that you weren’t a member of the community before you began attending conferences.  This fails to recognize the PHP conference community as a subset of the greater PHP community.  I believe this raises the stage higher than the audience and higher than the developers who use PHP daily.  I believe it puts space between the speaker and the audience.  I don’t like it!

Who is in the PHP community?

The conference community is a much smaller world.  You see a lot of the same people, and friendships form and you can see these people online in between conferences.  It’s fantastic!  And when speakers are traveling from to many conferences, they become even more familiar with each other.  The developer who can only attend a conference each year is less familiar.  This is a tight, supportive community, especially when you are known.  However, I firmly believe:

The PHP community is each one of us who use PHP or supports a PHP tool.  Because when we try to define community as anything less, we’re just forming cliques.

I learned a lot about PHP from 1999 to 2014.  PHP grew and changed A LOT in that time.  When I see the conference community represented as “The PHP Community” it very clearly omits my 15 years of experience.  It leaves out my peers on campus whose bosses don’t value continuing education for their developers.  Being in that space and relying on documentation alone to do your job and bring your skills up is HARD.  People in these legacy spaces are fighting an uphill battle to modernize their applications because the code quality is not valued by the people in charge.

Maybe, after all of this perseverance, they get to attend a conference.  They hear long lists of the new things they should be doing and judgements of how bad it was to do things the old way.  Then a motivating speaker defines community as these other people, and I just think it’s so backwards.

We are Community and So Can You!

I want to hear from the people who inherit these applications.  I want to hear how they’re overcoming challenges!  Because those projects are infinitely more useful to me than a talk about some new tool that isn’t even production stable yet.  I want to see the projects that succeeded and the ones that failed because there is so much learning there.  When we are speaking to people, we should be inspiring them to try something new.  We should be sharing tools they need, empowering them that they are valuable members of our community, and opening the floor to welcome them when they are finally ready to share that big project.

I feel very lucky that there were community members and speakers who encouraged me at conferences.  I know these talks mean to motivate people, and they also include a lot of history and support.  But it always bugs me when anyone labels the PHP Community as anything less than anyone who uses PHP. But I don’t always see that coming from the stage.  And the  stage has a louder voice.  I’d like to see that change a bit!

Bootstrapping Talk

I have been presenting ‘Pulling Up Your Legacy App By Its Bootstraps’ at conferences and user groups.  It’s been a treat for me because I am learning a lot by sharing what I have learned in this project, and it seems helpful to the audience.  I’m meeting people who are in similar work environments and when I get to the tools we used, I usually begin to receive questions.  This is what prompts the most questions after the talk, too.

The first few times I gave the talk, I received a lot of enthusiastic questions about migrations with Phinx.  Some of my audience had either not used a framework with migrations or didn’t know a tool was available outside of a framework, so they were eager to bring those into their projects.  I added code samples of change(), up(), and down() methods to my talk.

I have been improving my description of Dependency Injection and briefly answering the question “what is DDD” and “why did you need it”.  I believe I’ve better illustrated that point, but I feel like I haven’t answered those in the best possible part of my talk outline, and I’m trying to sort out where it may make more sense.

The last time I gave this talk, I received some comments that composer seemed awkward or was frustrating to use.  As I asked questions, I learned that the pain area was actually about wanting to exclude the vendor folder from their project’s repo.  I was able to share that we commit our composer.json and composer.lock files to the repo but ignore the vendor folder.  This seemed to solve that issue, but I am curious if there will be other composer questions in the future.

Now that I have been able to add more code and explanation of the tools we are using, I am reorganizing my outline and optimizing the talk based on the feedback I have received.  I really enjoy giving this talk and helping people.  I hope I’ll get to share it more.

Page 1 of 3

Powered by WordPress & Theme by Anders Norén