Tag: work

Creating A Public GraphQL API

graphql2017 saw the creation of several high profile public GraphQL APIs.  These GraphQL APIs are great for customer integrations, third-party integrators,  professional services and internal consumption.  When creating a public GraphQL API there are several important considerations.

Surface Area – Keep It Skinny

Deciding how much surface area to expose is important.  Exposing a too-limited set of apis and properties can result in an API that isn’t usable by some of your key consumers.  Exposing too many APIs and properties leaves you on the hook to support those APIs that you didn’t expect people to use, or in ways you didn’t expect them to be used.  The approach we took was to keep it skinny.  It isn’t just easier to add functionality when it becomes necessary.  Keeping the API skinny gives you a growth path and prepares API consumers for the continuous evolution which all public APIs inevitably go through.

Naming Conventions – Consistency Matters

Locking down simple naming conventions early is very important.  While the API is going to evolve, you don’t want to torture your customers with a continuous renaming of public APIs through new query/mutation names and the slow deprecation of old query/mutation names.  The naming conventions we settled on were:

  • createEntity, updateEntity, deleteEntity for mutation names
  • saveEntity for complex entity operations (create it if it doesn’t exist or update if it already exists)
  • entity to query an entity by id and entities to query entities using a variety of search criteria
  • Entity for type definition names
  • SearchEntity for the search criteria for a particular entity type

Deprecating Fields – Avoid Surprises

We use deprecated fields as a way to tag things that are going to go away.  The goal should be to keep deprecated fields for a couple major releases after tagging them as deprecated so you don’t surprise consumers when they disappear.  We also use deprecated fields as a way to tag experimental features.  These are warnings that the API is very likely to change and/or might only be partially implemented.  Again, the goal is to give consumers a hint so there are no surprises.

Architect For Reuse

Try to build architectural components that aid in resolving queries from similar data sources.  In our case, 60% of our current functionality uses existing REST APIs under the covers.  It was possible to build helpers to leverage the similarities that the REST APIs share so each query resolver, field resolver, sort order, etc. can leverage these reusable helpers instead of treating the implementation of each resolver as the first time.  We were able to build architectural components to help getting data from REST, direct SQL, Cypher queries to Neo4J and even another GraphQL endpoint.

Think About Testing

I recently blogged about our approach for creating a GraphQL integration testing framework.  Think about testing as you build out your API.  We created unit tests as developed the API, schema snapshot tests to catch accidental schema changes, and eventually full GraphQL integration tests that are completely independent of external datasources.  These tests will give you confidence that you haven’t broken things for your consumers as you iterate and improve your internal architecture.

Evangelize It

Teaching consumers about your awesome new GraphQL API is something you will want to do.  What is the point of developing such a wonderful and easy to use API if your customers, third-party integrators, professional services or internal developers don’t use it?  My advice for evangelizing any technology is the same – keep it simple.  GraphQL is new and often misunderstood.  Explain how your GraphQL API makes it super easy to get or manipulate data.  Explain how the hierarchical nature of GraphQL query results saves consumers from having to stitch results from several REST or DB calls together on the client side.  Keep it simple and approachable and pretty soon you’ll have consumers asking for enhancements, performance improvements and finding new and exciting ways to leverage your data!

 

Advertisement

GraphQL Integration Testing

graphql

Recently a colleague and I collaborated on a  unique approach to doing GraphQL integration testing.  Our unit testing setup already had the ability to test GraphQL resolver functions or helper functions used by the resolvers.  Our end to end testing can be done easily by bringing up a GraphQL server and running queries against it while it resolves those queries by accessing a real database or REST api.  What we designed for integration testing is somewhere in between.

Our approach gives you an end to end test of full GraphQL queries and mutations while automatically mocking external resources for you and comparing results against snapshotted data.

Goal: Test Full Queries With Easy Test Creation

The goal was to test a full query or mutation without using any external resources – no databases, no REST apis, etc.  We also wanted to make test creation easy – as easy as normal jest snapshot testing if possible.

Mock External Resources and Snapshot Results

We mocked external resources by running queries against a live system and capturing the interactions with external resources.  SQL queries and responses were recorded.  REST calls were recorded. After capturing the calls and responses we saved them in special directory similar to jest snapshots.  Each test case file would have a captured data file in the captured traffic directory.  When the test ran a 2nd time, the captured data would be used to prime the code where we made external calls by using sequealize and fetch wrapper objects.  When fetch is called, it uses the primed data to return the previously captured data. Likewise, when sequelize is called, the sequelize wrapper would use the previously primed data to return the previously captured data.

Start a GraphQL Server with Express Handlers

Next we started up our GraphQL server with some special express handlers that allowed us to prime or start/stop capture of interactions with external resources. We could have created GraphQL apis to prime/start/stop capture but we didn’t want to modify the public API that our customers interacted with.  Instead of modifying GraphQL to allow us to prime/start/stop capture we instead added conditional express handlers used only during integration testing runs.

First Run – Capture Data

When a test case is run without previously capture external data, the express server is told to start capture mode.  The query is run and the external interactions are captured.  After the query is run, the test case requests the just captured data and saves it in the captured data directory next to the test case.

Subsequent Runs – Use Captured Data To Prime Sequelize and Fetch Wrappers

The second time the test case is run, it primes the express server with the previously capture data, runs the query which uses the previously captured data for all external interactions and then compares the results with the snapshotted results.  This approach effectively tests all things inside GraphQL related to the query without using any external resources.

Putting It All Together

  • Start up a GraphQL server with special express handlers
  • Run all integration test queries/mutations against the GraphQL server just started
  • If a test is run without previously captured data:
    • Use the express handlers to start of capture of external interactions via REST or sequelize
    • Run the test
    • Get the captured data and save it in a special directory similar to jest snapshotted data
    • Use the express handlers to stop capture of external interactions
    • Run the next test
  • If a test is run with previously captured data:
    • Use the express handlers to prime the sequelize/REST wrappers with previously the captured data
    • Run the query/mutation which will use the previously captured data
    • Compare the results with the previously snapshotted results
    • Run the next test
  • Stop the GraphQL server

Python and Django

I’ve been doing some Python work for my day job so I started investigating the language and popular web frameworks.  I got python installed and read the python tutorial at python.org.  I build some simple Python classes and unit test cases using eclipse and the PyDev plugin.   The thing I like about Python is that the language is clean and there seems to be only one way to do most things.  Unlike Perl or Ruby where there are many ways to do anything, Python seems much less messy.  Working heavily in Python with good Python developers should be efficient and peaceful.

Then I  worked my way though the django tutorial which was pretty easy to follow.  Django generates most things for you and requires writing very little code for doing most common web tasks.  My impression was that seriously working with django would be pretty easy and efficient.

Like I said, I’ve been working with Python at work so I plan to post more about my impressions of Python as time goes on.  Stay tuned..

Busy Summer

I haven’t blogged in a while but I was just reflecting on how busy our summer was so I decided to write a quick blog post.  I had a trip to Raleigh, NC for work.  The kids had two different basketball camps, each a week long.  We took half week to go to a local water-park resort as a family trip.  As usual we had a bunch of summer birthdays to celebrate and we had some family come to town to visit.

The weather was hot.  It got hot early and stayed hot all summer long.  Unfortunately that meant that the kids spent most of their free time inside.  I took advantage by giving them summer writing assignments because both of them could use some work on their writing.  They improved a bit and mostly got over the pain of writing which was the biggest gain from my point of view.  Hopefully now when their teachers give them writing assignments they won’t worry about it as much.

School started up last week for the kids and school will start next week for my wife.  Pretty soon I’ll be sitting in my home office in a quiet house all day.

Organized Text Files

I finally gave up on all the tree based organizers like treepad and notecase.  Both work well but I have decided to use the lowest common denominator to save my notes – plain text files and for rare exceptions odt documents (LibreOffice/OpenOffice/LotusSymphony).

These are the features I wanted in a note taker:

  • Must be easy to use
  • Must work on all my computers (home, work, netbook, vmware images, etc)
  • Must be easy to transfer from one location to another
  • Must be easy to encrypt just those notes that contain private information
  • Must be searchable with Google Desktop
  • Nice to have: formatting
  • Nice to have: attachments (but that also creates a searchablity problem)

I used Treepad for a while and them switched to NoteCase.  Both are good.  But Google Desktop didn’t find me the node in the tree – it just found me the entire ncd file.

My System

My system now is just to take notes using plain text files with simple Markdown formating.  I title each file with a date (mm.dd.yy) and a topic (like personal) and a title (like something personal) so the file would be named

mm.dd.yy – personal – something personal.txt

I keep files organized into folders on the file system.  Most of the time my folder system saves me from searching but search still works to turn up results when I use Google Desktop Search to find something.

 

I Love The Hudson Library

Tomorrow we have another home showing.  That means I have to leave home.. but keep working.  The Hudson Library has private study rooms that you can reserve in advance.  They have a table and chairs, a free wired and free wifi internet connections and with the private room I can talk on my cell phone all I want with my team.  You can only reserve the room for 2 hours but that is plenty for my needs.

Not Going To Paris

I’m pretty glad today to not be booking travel for Paris.  Things are happening at one of our customer sites and my coworker is being sent off to Paris to investigate.  He is Canadian so he isn’t missing a holiday weekend.  I was worried I might get sent so I’m very happy it wasn’t me.. not this week.  It is possible that I could get sent some time in the next few months but who knows.

Back To School

The kids started school last week.  M is in 1st grade and Z is in Kindergarten.  They ride the bus together to and from all day school (we have all day kindergarten here).  So far Z likes it a lot.  D likes their teachers better than M’s teacher last year.  We took Z to his first day of school (camera and video camera in hand) and recorded the event.  He didn’t want us to come in – he wanted to just be a big boy and go on his own.  We had to drop him off at the right room so we went in with him.  He was fine when we left – no separation problems at all.  So big!

Connectivity Pains

Today I’m having serious connectivity problems to one of our customers in France.  I’m connecting to their system via a support machine in Great Britain and today it has just dropped me 5 times in a row.  I can’t get anything done!  OK, breathe deep, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.  I’m feeling better now.