DPS907 notes – week 3 – Sep 21 and Sep 24

Advice. More HTTP method handling. Associated data in web services. The “command” pattern.

 

Agenda for the Friday class

Here’s the agenda for the Friday class:

  • Q&A about advice about success in this course
  • More about supporting HTTP methods, PUT and DELETE
  • Working with associated data in web services
  • The “command” pattern

 

Code examples for this week

Remember, code examples are published on a public GitHub repository.

You can use a web browser to view the source code. You can also click the “Download ZIP” button to get a full and complete copy of all code examples in the repository. Code examples will be published weekly, in logically-named folders (e.g. “Week_03”, “Week_04”, etc.).

Associations Other

 

Advice about success in this course

We are starting the third week of the course, and your professor hopes that you’ve enjoyed it so far. This section of the notes has advice on how to improve your performance in the course, get the most out of it, and earn the highest grade that you can.

The following advice is for every student in the course. It will also work for other courses in our School of ICT software development programs. Here’s the advice:

 

Prepare

Prepare before every class. Your professor expects you to have read and studied the notes, including the linked and recommended readings. You must perform some learning activities before class. You don’t need your professor to verbally dictate content that you can consume better and more efficiently on your own. Therefore, make it a habit to prepare before class.

Readings are important. It is impossible to learn what you need to learn in this course, by simply listening to your professor talk for ninety minutes each week. It is also impossible to learn what you need to learn simply by writing code, and ignoring all of the good advice and best practices that are communicated to you through the readings.

The way you work through the content is important. Don’t just move your eyes over the content, with the support of a partially-engaged and distracted brain. Instead, read critically, concentrate, and think as you read. Read the difficult or challenging topics out loud (with your speaking voice!). Look up words or terms that are unfamiliar. Open and study the code examples (using Visual Studio), while you are working through the content. Follow the links to the linked material, and work through that too. Write down questions that you need answers to (and follow up by asking your professor or someone else in your support-and-learning network).

 

Review

Review the course content. Every week. How?

Schedule a regular time to do this work. You have an appointment calendar on your computer or phone – use it. When? Whatever works for your schedule, but it may be useful to do this activity on Monday, Tuesday or Wednesday, because you will recall techniques and best practices that will be useful as you work on the next assignment. (The professor has drop-in help times on Monday and Wednesday afternoons.) Also, it will help you “study” for the periodic Friday test.

Review the material in sequence. Two sequences could work: New-to-old, or old-to-new. In other words, you could start with the most recent material, and work backwards, day by day, to the oldest material. Alternatively, you could start with the oldest material, and work forwards to the current material.

Is there a benefit to a regular review? Yes. Ask yourself a question, and answer it honestly: Have you ever read something technical for a second (or third) time, and “discovered” the real meaning of something that you know you have read before? The answer will always be “yes”. It’s natural, and it’s part of being human.

Some students establish a “study group” with a few classmates. That’s a good practice. Quiz each other. Have each member be responsible for digging deep into a specific topic, and reporting the results to the others.

 

Resources

Use the recommended resources. There’s “gold” in the resources. Don’t ignore the resources that you think are too dense, or technical, or boring. Read them. Re-read them. If you begin to read content that’s unfamiliar, or beyond your current level of knowledge or understanding, you should still skim/read it. That way, when you later raise your level of knowledge and understanding, you will remember the material, and can handle it.

 

Assignments

When working on the programming assignments…

Follow instructions.

Make a “coding plan” before you begin writing code. Whatever form works for you, use it:

  • flowchart
  • pseudocode
  • comments inside empty methods/classes
  • English-like statements
  • boxes-and-arrows

Whatever works for you.

Do not copy-paste code, hoping that it will work. Write your code without using copy-paste. Later, when you realize that you are writing and repeating the same code as before, then you can consider using copy-paste. And, you should look for opportunities to refactor your code.

As stated in the assignment specifications, your professor believes that the best way to work through any assignment is to do it incrementally. Get one thing working correctly, before moving on to the next. Test each part.

 

Tests

When working on the tests…

Understanding a test question is important. Make sure you are answering the question, and not some other question. Ask your professor – during the test – if you’re unsure. (For best results, come up to the front of the room, to the professor, to ask your question. That way, you’ll have some privacy.)

Understanding the question format is important too. Our questions are conversational in nature. They skew towards applying the knowledge you’re learning. They’re never trivial. The overall goal is to help you become a better explainer, in writing, and verbally. That will pay off in future work/career opportunities.

 

And now, on to this week’s topics…

 

Supporting all relevant HTTP methods, PUT and DELETE

Recall that this content was split over two weeks, last week and this. Last week, we focused on the easier group of HTTP methods, GET and POST. This week, we will cover PUT and DELETE.

A reminder, Section 4 of RFC 7231 specifies the HTTP request methods. Please read/skim sections 4.1 and 4.2 now.

As you can see in Section 4.3, there are many methods available. In this web services course, you will learn to work with a subset of methods, which we call the “relevant” methods.

The code example AllHttpMethods will help you learn to support all relevant HTTP methods.

In addition, you will learn to create the correct response, which will be an error (as noted in a later section), or one of the results in the following table.

Request Return type Status code Comment
GET collection Collection 200
GET collection Empty collection 200 “Empty” is not an error condition
GET one One 200
GET one No item 404 Truly is ‘not found’
POST add item The added item 201 Added item typically includes an identity property
PUT item updated The updated item 200
DELETE item (no content) 204 The response body for DELETE requests have not been defined

 

Coding principles

Review the coding principles from last week’s notes.

 

“Update existing” explained

In the manager, “update existing” first attempts to fetch the existing object. If the existing object does not exist, null is returned.

Alternatively, if successful, it has a reference to the object, and will proceed to update the object, and then return the updated object:

  1. ds.Entry(p) is the reference to an object “p”
  2. .CurrentValues is the object’s collection of current values
  3. .SetValues(updatedP) will update/change those values with the new supplied values

The SetValues method ignores missing properties, as well as navigation properties to associated objects. Very nice, very convenient.

In the controller, you must first check the model state. At the same time, for “update existing” scenarios, you must ensure that the identifier on the URI matches the identifier in the request entity body. If the data is bad, return BadRequest().

This step guards against some kinds of attacks.

 

Alternatively, if successful, call the manager method. If successful, return an Ok() result and the updated resource.

 

“Delete existing” explained

In the manager, “delete existing” first attempts to fetch the existing object. If the existing object does not exist, do nothing (but in the future, we’ll improve upon that).

Alternatively, if successful, it attempts to remove the existing object from the collection. This attempt is guarded by a try-catch block. The attempt may fail, because the existing object may be associated with other objects.

In the controller, we simply call the manager method. We don’t care if the object exists, because we don’t want to reveal too much information (to the requestor) about our entity collection.

 

Associations among entity classes

In your web apps courses, you probably had some coverage of the kinds of associations (relations) that data entities can have. In the previous class session, we refreshed your memory about one to many associations.

Today, we’ll discuss some others, and study a code example (named AssociationsOther):

  • one to one
  • many to many
  • self-referencing one to one
  • self-referencing one to many

The problem domain that the code example covers is a workplace. There are three entities, Employee, JobDuty, and Address.

A workplace has employees. Employees have job duties, usually one or more. However a job duty is often performed by many employees. Also, an employee lives somewhere, and works somewhere – these are addresses.

The class diagram below is from this week’s code example, AssociationsOther. Click to open it full-size in its own tab/window.

ClassDiagramOfOtherKindsOfAssociations

 

One to one

An Employee has one “home” Address, and one “work” Address.

From the Address perspective, it is linked to an Employee.

When writing the entity classes, you must know the following, and be aware of some rules:

  • In this association, you MUST select a “principal” end of the association, and a “dependent” end
  • We will decide that the Employee is the principal end
  • This means that an Employee object can OPTIONALLY have an associated Address object – an Employee object can be created, without having an already-existing Address object
  • However, as a result, the Address is the dependent end
  • This means that an Address object MUST have an associated Employee object – an Address object cannot exist without an associated Employee object, so when you create an Address object, you must know about the associated Employee object

How do you code this?

It’s simple. Two tasks:

In the dependent class (Address), add the [Required] data annotation attribute to the navigation property that points to the principal class. Here, in other words, add [Required] to the “Employee” property.

[Required]
public Employee Employee { get; set; }

Add another property, a nullable int. Its name is a composite name – EmployeeId.

public int? EmployeeId { get; set; }

How do you use this?

  1. Make sure that you have a reference to a principal object (e.g. an Employee)
  2. When creating a dependent object (e.g. an Address), set its “Employee” property to the principal object
  3. Set its “EmployeeId” property to the principal object’s identifier

 

Many to many 

An Employee can have several “job duties” (e.g. professor, researcher, coordinator), and a “job duty” is performed by many Employees (e.g. School of ICT coordinators include Peter McIntyre, Ian Tipson, Nagham Kubba, etc.).

Maybe surprisingly, this is also actually easy. Simply add collection properties to each class, similar to a “one to many” association.

 

Self-referencing one to one, to the same entity

An Employee can have a supervisor/manager, who is also an Employee.

This association is not required. In other words, it is possible that an employee will NOT have a supervisor/manager.

Notice that this scenario is a bit different from the Employee + Address scenario described above. In that scenario, there was a “principal” end of the association, and a “dependent” end. As a result, when adding a new address, we were required to provide the link to the employee. That’s why we used the [Required] attribute.

When writing the entity class for this scenario, you must know the following, and be aware of some rules:

  • Two properties are required
  • One property is a nullable int – it will (optionally) hold the identifier of the associated object
  • The other property is the class data type

For example:

// Self-referencing one-to-one
// Two properties are required
public int? ReportsToEmployeeId { get; set; }
public Employee ReportsToEmployee { get; set; }

It is used in a similar way to the other one-to-one scenario:

  1. Make sure you have a reference to the supervisor/manager (e.g. an Employee)
  2. When creating or configuring the worker, set its “Employee” property to the supervisor/manager object
  3. Set its “EmployeeId” property to the supervisor/manager object’s identifier

 

Self-referencing one to many, to the same entity

A supervisor/manager Employee has a collection of Employees supervised/managed.

This is actually easy, as you may speculate. Simply add a collection property; its data type is the class data type.

 

Are associations always required?

When you are writing entity classes, are associations required among all classes?

No.

It is not necessary to ‘connect’ every class to another. This technique is often used for data that is used for lookup or validation purposes.

 

Learn more about this topic theme

In this web services programming course, and in the prerequisite web apps programming course, we use a learning strategy that enables the student to focus on the important and most-used associations among entities. The Entity Framework, and its technologies, offers much more than we have time to cover in this course.

Therefore, as you read/skim the linked resources below, use your critical thinking skills to put a topic into the proper context and usage pattern. In other words, don’t be literal in how you use and apply the information.

The biggest difference-maker for us is that we are writing web services and web apps. As a result, operations on data are atomic – a read is done as a database server connection open, a read, and an immediate close. Similarly, a write is done as an open, a write, and an immediate close. Many of the discussions in the linked documents (below) are for runtime environments where a database connection is persisted as a longer-lifetime object. So, if you have questions about syntax and differences with what you’ve learned so far, ask your professor.

Microsoft – Entity Framework Relationships & Navigation Properties

Microsoft – Entity Framework Code First Conventions, Relationship Convention section

Morteza Manavi – Associations in EF Code First – a multi-part series; parts 1, 2, and 3 are useful

MSDN Entity Framework topic page, lots of good stuff here to pick-and-choose from

 

Handling ‘commands’ in a web service

In the past few weeks, we have been learning to design and code a web service by thinking of it as an API to a database-like data store. You have learned how to handle the typical CRUD operations (create, retrieve, update, delete) normally associated with data management. The HTTP methods map nicely to these operations, and that familiarity has helped you make progress.

It’s time to expand our thinking, beyond data management. How? By adding the ability to handle commands and operations that may or may not be easily mapped to data management. (Yes, in most cases, the command will change the data/state of one or more resources.)

What kind of commands or operations could be done? Anything. For example, you could cause the web service to send a message (e.g. an email, or text message) to a list of pre-configured recipients, and then log the action. Or, it could increase the hourly wage 5% for all employees in a certain department. Or, set/save a photo for a resource. The point is that the web service is now doing a better job of servicing a use case.

 

How to think about this concept

A web service is not always intended to be simply a thin layer on top of a data store (but sometimes it is).

Instead, it is often intended to be a gateway to the wide-ranging richness of an application / problem / business domain – all of its operations and workflows.

Today, you’ll get a gentle introduction to this concept. This will prepare you for more interesting scenarios in a few weeks. You can – and should – practice this concept in the next assignment.

 

Implementing this concept

There are two ways to look at any of the example tasks described above:

  1. As a command, where we state our intent – do this, or do that
  2. As a data management task, where we specifically, technically, and atomically set/update data properties to specific values

Which is the more natural concept to understand? Everyone can understand #1. Only programmers would care enough to understand #2.

How do we map commands to resources?

By convention, we typically send a PUT request to a resource. The underlying method has code that carries out our intent.

To illustrate this concept, study the AssociationsOther code example. It implements a command that enables a request to set (or configure) an employee with a supervisor:

request-command-flow

 

A command needs the following code:

  • A resource model, that defines the necessary data
  • A controller method that listens for the request
  • A manager method that does the work

Study the following diagram, and then the AssociationsOther code example. Click the diagram to open it full size in its own tab/window.

command-pattern

 

Is this a standard?

No, but it’s a principle named “command-query separation“, or CQS.

CQS states that a command does something but does not return data to the caller. (In contrast, a query does not change the state of the data, but it does return data to the caller.)

Therefore, the controller method return type will be void, which automatically creates an HTTP 204 status code. In other words, when handling a ‘command’, we simply execute the command silently, without any data feedback to the requestor (other than the HTTP 204, which is one of the HTTP success status codes).

It is also possible that you could decide to return HTTP 202 (Accepted). Some developers and thought leaders advocate this alternative, for some situations. Please carefully read the RFC, and then decide whether it is suitable for your use case.

Command query responsibility segregation (CQRS) – described here by Martin Fowler – applies the CQS principle by using separate Query and Command objects to retrieve and modify data, respectively.

 

What else do I need to know?

Here’s a few other important things to know about HTTP.

In HTTP, the GET method is safe. A safe method does not change the state of a resource.

These methods are unsafe: POST, PUT, DELETE.

We must also consider idempotence. In brief, a method is idempotent if repeated execution has the same effect.

In HTTP, GET, PUT, and DELETE are idempotent. (Why? Think about it.) POST is not idempotent.

 

Interesting readings

Exposing CQRS Through a RESTful API – Ali Kheyrollahi

 

(End of Friday content; Monday content is next.)

 

Agenda for the Monday class

Here’s the agenda for the Monday class:

  • Brief review of the essential web service building techniques
  • Work on the assignment

 

Essential web service building techniques

The assignments are complete. The coverage in the past few weeks should have enabled you to do a really good job on them. Recognizing the fact that it may have been awhile since your ASP.NET MVC web apps course, and the fact that many new topics have been covered in the past few weeks, we can have a brief point-form review (and in-class discussion) about the essential web service building techniques.

  • Recognize the fact that the HTTP standard (RFC 7231) governs all that we do (and has the answers to any questions that arise)
  • Start with and know the plan that you will follow to implement the web service
  • Gather all the tools needed
  • Know what data is involved, and where the data is located
  • Design a well-architected code base
  • Ensure that the manager class is devoted to app logic and data service operations
  • Plan and implement the controllers on a per entity (or entity group) basis, and/or on a per task basis
  • Know the use cases for your interactions – how they ought to work, and the data involved
  • Use the technologies that will enable modularity and scale, including resource models and AutoMapper
  • Incrementally test and debug when required
  • If you’re not sure about something, ask someone who has an authoritative and correct answer

 

Work on the assignment.

Start work on the next assignment.

 

 

 

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
%d bloggers like this: