Blog

Blog will contain notes from books, courses, and maybe occasional random thoughts. Most of the notes will come from my Obsidian vault served here as a backup using markdowntohtml.com with minimal extra formatting.

Notes will be added as I think they are relevant and polished enough to publish.

Table of Contents


Becoming an Effective Writer

What is and is not Business Writing?

Regular consistent practice is necessary. Changing habits is not easy; you have to be willing to change, know how to change, and practice. "Practice makes perfect"

Readers Writers
Scan for key points Be clear and simple
Quickly decide importance Get to the point

In order to succeed in business, you must be able not just to write, but to write effectively.

Principles of Business Writing

  1. Analyze the reader
    • What does my reader already know? Who is my audience?
  2. Organize the message
    • Does your message begin with a purpose, organize the message in the best way for the reader, and look easy to read?
  3. Signal the next step
    • Is there a time when a response is needed and does it contain contact information?
  4. Value the reader
    • Effective business writers need to give the impression that the reader is important and not just another number.
  5. Ensure an effective message
    • Decrease the need for follow-up messages.
  6. Choose the right channel
    • Email, Teams, Meeting, or Face to Face

The 10 C's of Business Writing

A writer has the right to expect every message to be: Complete, Concise, Clear, Conversational, Courteous, Correct, Considerate, Concrete, and Credible.

  1. Complete: Is all of the information included so that follow-up questions are not necessary?
  2. Concise: Use the fewest number of words possible. Including more words into your writing leads the reader to have to wade through information that may not be relevant to the writing.
  3. Clear: Have you thought about what the reader knows or doesn't know, or are you writing based on what you know and what makes sense to you?
  4. Conversational: Does your writing sound as if you are writing to a human or to a robot?
  5. Courteous: Is your tone pleasant? Have you shown the reader how they will benefit from your information or policy? Does the message sound demanding or is it all about the writer's interest?
  6. Correct: Is your writing accurate and professional, or does it give the impression that it was rushed and not prepared?
  7. Coherent: Does your writing look jumbled or do the ideas tie together smoothly?
  8. Considerate: Does your writing look inviting to read (using headings and bullets) or does it use 1 or 2 long paragraphs?
  9. Concrete: Have you included specifics and examples, or are vague meaningless words used?
  10. Credible: Are all facts within the article given from trusted sources and cited?

Strong vs. Weak Verbs

Which of the following statements sound stronger and more concise?

(a) You will need to send your confirmation for your appointment by Friday. (b) Please confirm your appointment by Friday.

12 words versus 6 words. Not only is (b) stronger, the message is more concise. Look for camouflaged words in your message, verbs that have usually turned into nouns, commonly adding the -tion at the end of the word. Conversation versus confirm.

The same principle applies for filler words.

(a) There are five people who want to attend the meeting. (b) Five people want to attend the meeting.

Make your writing more concise, cut out the fluff and get to the point.

Create a Clear Message

Understand your reader and their ability to comprehend what you're trying to tell them.

Make your message logical and easy to read for the reader. Your main idea should be at the top of the paragraph, utilize transitional words (first, second, although), consider the connotation of the words that you use.

Example 1: "Hey John, I need you to talk about something urgent when you have time."

What would John think about in this message? What's so urgent?

Example 2: "Hey John, we need some help understanding the requirements in this ticket [link ticket here], specifically we have questions about… [list your questions here]"

In this 2nd message John knows exactly what ticket you're referring to, the exact questions you have, and knows to be prepared to answer these questions. Most of all, no worry about what exactly this urgent matter is.

Cut to the Question

Inspired from: https://nohello.net/en/

If you are asking a question to a co-worker, ask the question. Letting the reader know exactly that you have a question will get an answer faster.

Example 1: Bob: Hey John: How's it going? Bob: What time is the meeting? John: Oh, 3:30 today.

This includes common opening phrases "How are you?" or "Hey want to hop in a call?". Putting the reader on the spot dissecting a question in a call can make the recipient feel pressured to get the answer now. If you just ask the question first, you'll get the answer faster.

Instead consider this:

Example 2: Bob: Hey, what time is the meeting? John: Hey, 3:30 today.

Straight to the point, no extra words or messages needed.

Avoid Negative Words

Negative words can lead to negative reactions.

How would you react if someone tells you "You can't.", "You won't be able to.", "You failed."? Human nature is such that you immediately become defensive to language like this. Instead, you should focus on what is and can be.

Example 1: "I won't be able to get to your review until Friday." Better: "I will get to your review on Friday."

Example 2: "You can't reserve Room 110 on June 10th." Better: "Room 111 is already reserved for June 10th, but is available on the 9th or the 11th."

Phrase your writing to offer alternatives to phrases that are usually negative. Be assertive on the 'when' something will happen or change.

Using positive language requires more thought, but is well worth the effort put in to better assist the reader.

Further Reading


The Theory Behind Contract Testing

Below are my notes from the first half of Contract Testing in Action, highly recommend this book as this is only the spark notes. Many of the fine details have been left out and are left for the book to describe.

What contract testing is and why it matters

Contract testing is a form of testing where you test that two systems have a shared understanding of expectations.

The contract is a JSON file containing the names of two systems interacting. It is the web interface interacting with an API. The contract lists all possible interactions between the two systems.

There is a shared broker (the contract) which the API can access directly. The API pulls down the contract from the shared broker and replays the expected request from the web app and then compares that all responses exist.

When there are two users of an API, for example a Mobile client and a Web App, a separate contract can be introduced to ensure that changes within the API won’t break either of the applications.

Apart from detecting bugs missed by proper communication amongst teams, here are other reasons why contract testing can be helpful:

Contracts on the Consumer Side

Usually the contract is driven from the consumer of the API. Usually the consumer will receive business requirements for an application, thus they will create a contract for what fields that they will need.

The frontend engineer will

Contracts on the Provider Side

Contracts will generally be stored in a separate project repository, one of the backend engineers is notified if there are updates to the contract. The responsibility of the provider is to verify the contract.

The backend engineer will

Contract testing is only useful when you have both a provider side contract and a consumer side contract.

How Contract Testing Fits

Contract testing is in between the layer of Integration tests and Unit tests. They provide high confidence that API endpoints are shaped correctly and allow the developer to confidently know an endpoint will return the data needed. Providing early feedback to find any discrepancies and misunderstandings between two teams before deploying an application and running integration tests, mitigating compatibility issues found between E2E and integration tests.

Contract testing does not replace any of the aforementioned tests, it compliments them.

Contract testing does not solve:

When deciding whether to remove a integration or E2E test to a contract test, a good rule of thumb is to move tests that can be completely duplicated at the contract level. This gives you confidence that you don't need this as an integration or E2E test. Defining clear contracts between a consumer and a provider ensures that developers will only deliver functionalities that align with the consumers needs.

Technical Overview of Contract Testing

What is a Consumer?

Contract testing puts more power in the hands of the consumer. In day-to-day life, a consumer in a retail situation is a "user of a product or service". Each user may use their product slightly differently and/or have different uses of the product.

The consumer as it relates to us is generally a web or mobile application that makes requests to a backend service. But a consumer can also be a service that is calling another backend service.

In a consumer-driven approach to contract testing, the consumer is driving the contract. In the example of a login, a consumer dictates when the application requests the login data. An end user does not care about the shape or the data, they only care about whether they can log in or not. This is why the consumer is so integral and should influence the expected data response.

What is a Provider?

A provider is "something that someone needs or wants, if somebody wants your product, you provide them with it or make it available". In a consumer driven approach, the consumer will mock out the provider and the provider mocks out their downstream dependencies.

The provider must add a test pointing to the consumer within the contract testing process and will automatically get updates if they point to the latest version of the consumer contract.

What is a Contract?

A contract is “a legal document that states and explains a formal agreement between two different people or groups”. It is important to distinguish the differences between a contract and a schema. A schema is described as "an outline of a plain or theory". The schema provides the outline, it will be defined in the planning phases before development starts. A contract is used after development to ensure the schema does not change after released.

What is a Contract Broker?

A broker is “a person who talks to opposing sides, especially governments, making arrangements for them or bringing disagreements to an end“. A contract broker is the central place that contracts are stored. Without a broker, passing around contracts is manual and can lead to different versions of the most recent contract due to code changes.

Implementing Consumer Driven Contract Testing (CDCT)

The Focus of a Consumer Contract

A consumer contract is only supposed to make sure that when a consumer asks for data from a provider service, the correct data is returned as specified by the contract agreement. This does not care about the functional details of how the provider works, instead they focused on what the consumer needs and checks if they get it.

A general rule of thumb when deciding what to include in the contract is: "If I don't include this scenario, what bug in the consumer or what misunderstanding about how the provider responds might be missed. If the answer is none, don't include it." source

Building with LEGOs

It is important to understand coupling with contract testing. Think of coupling in the context of LEGO blocks. In a highly coupled scenario, LEGO blocks are intertwined and connected with other blocks, if you remove 1, the whole structure falls. These blocks are highly dependent on each other and depend on one block being present.

In contract testing you are able to smell a highly coupled contract if you make one small change to the provider and the consumer contract fails. If you're not careful, contract tests can easily become very brittle and flaky.

To combat flaky tests, Pact provides loose matchers, such as type based matchers. With type based matching, you care about what is the type of data returned, rather than the actual data itself. Consider the code sample below

      
      const EXPECTED_BODY = {
          id: like(1),
          username: like('marie'),
          fullname: like('marie cruz')
      }
    

This object represents the shape the consumer expects from the data provider. If the consumer makes a GET request, it cares that the data exists, and the type of the data matches. Another question that Pact recommends is "If I made this looser/tighter, what bugs would I miss/prevent?"

Example Consumer Jest test

A consumer contract test can be broken down into 5 steps

  1. Importing the required dependencies.
  2. Setting up mock provider that the consumer will use.
  3. Registering the expectations that the consumer will receive from the provider.
  4. Verifying the consumer test and generate the contract.
  5. Publish the contract to a broker.
      
      const path = require("path");
      const { fetchMovies } = require("./consumer");
      const { PactV3, MatchersV3 } = require("@pact-foundation/pact");
      
      const provider = new PactV3({
        dir: path.resolve(process.cwd(), "pacts"),
        consumer: "WebConsumer",
        provider: "MoviesAPI",
      
      });
      
      const EXPECTED_BODY = { id: 1, name: "My movie", year: 1999 };
      
      describe("Movies API", () => {
        describe("When a GET request is made to /movies", () => {
          test("it should return all movies", async () => {
            provider
              .uponReceiving("a request for all movies")
              .withRequest({
                method: "GET",
                path: "/movies",
              })
              .willRespondWith({
                status: 200,
                body: MatchersV3.eachLike(EXPECTED_BODY),
              });
      
            await provider.executeTest(async (mockProvider) => {
              const movies = await fetchMovies(mockProvider.url);
              expect(movies[0]).toEqual(EXPECTED_BODY);
            });
      
          });
      
        });
      
      });
      

The test above generates a contract WebConsumer-MoviesAPI.json using Pact to be uploaded to a shared broker.

Implementing CDCTs for Providers

When developing contract tests, it is essential to keep in mind that there are two sets of tests that you need to write, one for the consumer, the other for the providers. Provider contract tests typically demand less code than it's counterpart.

The Focus of a Provider Contract Test

The primary focus of a provider contract test is to verify the contract that the consumer has generated. Contract testing tools, such as Pact, provide a framework that allows data providers to pull the contract test and replay the interactions that the consumer registers as part of the contract.

A consumer-driven contract testing approach forces the provider to only develop features that the consumer requires. If the API introduces a breaking change that modify the type of a field, the contract should verify this change before applying it to production. To reiterate, contract testing should NOT verify validation, this should be a unit test.

If the provider changes the business logic of a validation, this would break a contract testing validation. Ideally business rules should not break a contract with a consumer.

Using Provider States Effectively

Provider states allow data providers to define the state a response needs to be in to be able to verify the interaction from the consumer contract successfully. When writing a provider contract test with provider states, you need to make sure that the provider state is provided from the consumer.

  1. Set up the consumer test with a provider state.
  2. Define the state of the provider.

Example Provider Jest Test

A provider contract test can be broken down into 5 steps

  1. Importing the required dependencies.
  2. Running the provider service.
  3. Setting up the provider verifier options.
  4. Writing the provider contract test.
  5. Running the provider contract test.
const { Verifier } = require('@pact-foundation/pact');
      const { importData, server } = require('./provider');
      
      importData();
      
      const port = '3001';
      const app = server.listen(port, () => console.log(`Listening on port ${port}...`));
      
      const options = {
          provider: 'MoviesAPI',
          providerBaseUrl: `http://localhost:${port}`,
          pactBrokerUrl: process.env.PACT_BROKER_BASE_URL,
          pactBrokerToken: process.env.PACT_BROKER_TOKEN,
          providerVersion: '1.0.0',
          publishVerificationResult: true,
          consumerVersionTags: ['main'],
      };
      
      const verifier = new Verifier(options);
      
      describe('Pact Verification', () => {
          test('should validate the expectations of movie-consumer', () => {
              return verifier
                  .verifyProvider()
                  .then(
                      output => {
                          console.log('Pact Verification Complete!');
                          console.log('Result:', output);
                          app.close();
                  });
          });
      });