[.NETWorld] Five things every developer should know about software architecture

Now I may be biased, but a quick look at my calendar hints to me that there’s a renewed and growing interest in software architecture. Although I really like much of the improvement the agile movement has provided to the software development industry, I still can’t help feeling that there are a large number of teams out there who struggle with a lack of process. After all, not every team is staffed with rockstar engineers! Although we’ve moved away from heavy prescriptive process frameworks, at least they provided a starting point for many of the activities associated with software development … and this includes software architecture.

Put very simply, software architecture plays a pivotal role in the delivery of successful software yet it’s frustratingly neglected by many teams. Whether performed by one person or shared amongst the team, the architecture role exists on even the most agile of teams yet the balance of up front and evolutionary thinking often reflects aspiration rather than reality. The big problem is that software architecture has fallen out of favour over the past decade or so. Here are five things that every software developer should know about it.

1. Software architecture isn’t about big design up front

Software architecture has traditionally been associated with big design up front and waterfall-style projects, where a team would ensure that every last element of the software design was considered before any code was written. Software architecture is basically about the high-level structure of a software system and how you get to an understanding of it. This is about the significant decisions that influence the shape of a software system rather than understanding how long every column in the database should be.

2. Every software team needs to consider software architecture

Regardless of the size and complexity of the resulting product, every software team needs to consider software architecture. Why? Put simply, bad things tend to happen if they don’t! If software architecture is about structure and vision, not thinking about this tends to lead to poorly structured, internally inconsistent software systems that are hard to understand, hard to maintain and potentially don’t satisfy one or more of the important non-functional requirements such as performance, scalability or security. Explicitly thinking about software architecture provides you with a way to introduce technical leadership and stacks the odds of a successful delivery in your favour.

3. The software architecture role is about coding, coaching and collaboration

The image that many people have of software architects is of traditional “ivory tower” software architects dictating instructions to an unsuspecting development team. It doesn’t need to be like this though, with modern software architects preferring an approach that favours coding, coaching and collaborative design. The software architecture role doesn’t necessarily need to be undertaken by a single person plus coding is a great way to understand whether the resulting architecture is actually going to work.

4. You don’t need to use UML

Again, traditional views of software architecture often conjure up images of huge UML (Unified Modeling Language) models that attempt to capture every last drop of detail. While creating and communicating a common vision is important, you don’t need to use UML. In fact, you could argue that UML isn’t a great method for communicating software architecture anyway. If you keep a few simple guidelines in mind, lightweight “boxes and lines” style sketches are an effective way to communicate software architecture.

5. A good software architecture enables agility

There’s a common misconception that “architecture” and “agile” are competing forces, there being a conflict between them. This simply isn’t the case though. On the contrary, a good software architecture enables agility, helping you embrace and implement change. Good software architectures aren’t created by themselves though, and some conscious effort is needed.

[.NETWorld] Implementing CRUD Activities in a TypeScript ViewModel

In this column I’m going to show how to integrate create, read, update and delete (CRUD) functionality into your client-side application using TypeScript. But first, I need to address how to integrate your entity objects with the requirements that might be imposed by a JavaScript library.

Integrating Entities by Extending Interfaces
It isn’t unusual for a JavaScript library to add new functionality to objects or classes you create. For example, I use the IdeaBlade’s free Breeze library to manage the client-side objects retrieved from methods on my server-side services. To support managing client-side objects, Breeze adds an entityAspect property to my objects as it retrieves objects from the server. That entityAspect property contains state information about the object. To notify Breeze that an object’s to be deleted, I call the setDeleted method on the object’s entityAspect property.

In TypeScript, when working with server-side objects after they’re downloaded to the browser as JSON objects, I don’t have access to those objects’ C# or Visual Basic definitions. To provide a definition of those objects that my client-side code can use, I create a TypeScript interface that duplicates my Visual Basic or C# definition. With Breeze, however, I need that TypeScript interface to also include the methods and properties that Breeze adds to my objects as part of downloading them. Unlike the server-side objects I created, however, I don’t know what the Breeze properties and methods look like. Fortunately, TypeScript provides extended interfaces to handle this issue.

To have my client-side interface include the methods and properties that Breeze adds to my client-side objects, I define the interfaces for my objects as extensions to interfaces exposed by Breeze. The Breeze interfaces I need, for example, are defined in a class called breeze.Entity. This means the interface that describes my Customer object, with its three properties and including the Breeze extensions, looks like this:

module PHVEntities 
{
  export interface ICustomer extends breeze.Entity 
  {
    Id: number;
    FirstName: string;
    LastName: string;
  }

Now, my Customer interface includes the Breeze entityAspect property defined in breeze.Entity. I can mark a Customer as deleted with code like this:

cust: PHVEntities.ICustomer;
...download customer object...
cust.entityAspect.setDeleted();

Implementing CRUD
With that interface in place, I can use Breeze to retrieve Customer objects from my server-side services. Listing 1 shows the start of my ViewModel (written with Knockout) with the code that does the retrieval and puts the objects in an array called customers defined in the ViewModel constructor.

Listing 1: A Knockout ViewModel with Breeze

import b = breeze;
import ent = PHVEntities;  

export class SalesOrderVM
{
  constructor(
    private em: b.EntityManager = new
      b.EntityManager("...url for services..."),
    public customers: KnockoutObservableArray<ent.ICustomer> = 
      ko.observableArray<ent.ICustomer>()) { }

  fetchAllCustomers()
  {
    b.EntityQuery
     .from("Customers")
     .using(this.em)
     .execute()
     .then(dt => {
                    this.customers(<ent.ICustomer[]> dt.results);
                 })
     .fail(err => { "Problem:" + alert(err.message); });
   }

I have a button on the page that runs this method through a Knockout binding:

<input type="button" value="Get Customers" data-bind="event: { click: fetchAllCustomers }" />

After retrieving a collection of Customer objects, I display those Customers in a table. The HTML that binds to my customers collection generates a table that includes a button that binds to another method in my ViewModel:

<table>
  <tbody data-bind='foreach: customers'>
    <tr>
      <td><input type="text"   data-bind='value: Id' /></td>
      <td><input type="text"   data-bind='value: FirstName' /></td>
      <td><input type="text"   data-bind='value: LastName' /></td>
      <td><input type="button" data-bind='click: $root.removeCustomer' 
                 value="Delete" /></td>
    </tr>
  </tbody>
</table>

Each row in the table represents a single customer object. If I were to just bind my button to “removeMethod” then Knockout would look for the method on the customer object. Using $root tells Knockout that I want it to look for the method on the ultimate parent: my Knockout ViewModel.

Deletes, Inserts and Updates
In the removeCustomer method tied to the button in each row, I must do two things. First, I need to mark the Customer in the row as deleted to cause Breeze to trigger deletes back at the server. Second, I need to remove the Customer from my client-side customers collection so that it will no longer appear in the table.

Knockout will automatically pass the Customer in the row to a method called from that row, so the removeCustomer method looks like this:

removeCustomer(cust: ent.ICustomer)
{
  cust.entityAspect.setDeleted();
  this.customers.remove(cust);
}

Following my table, I have another button that allows the user to add a new row. That button also binds to a method on my ViewModel but, because the button is outside the context of the repeating rows in the table, I don’t need to qualify the method name:

<input type="button" data-bind='click: insertCustomer' value='Add Customer' />

My insertCustomer method also does two things. First, it uses Breeze to create a new customer entity and places it in a variable I’ve called newCust. The method then adds that newCust object to my customers collection:

insertCustomer()
{
  var newCust: ent.ICustomer;
  newCust = <ent.ICustomer> this.em.createEntity("Customer");
  this.customers.push(newCust);
}

Adding newCust to my Knockout-enabled collection causes Knockout to refresh the table and display the new blank row for the user to enter data.

I don’t need to do anything to support updates: The user can update the textboxes in the table that displays the customer’s properties. Thanks to Knockout, those changes are saved back to my collection of Breeze-enabled customers. All that’s necessary to have those changes (including inserts and deletes) sent back to my service is to call the Breeze SaveChanges method. I put that code in a method in my ViewModel called saveChanges:

saveChanges()
{
  this.em.saveChanges()
         .then(sr => {alert("Saved " + sr.entities.length + " Customer(s)")})
         .fail(err => {alert(err.message)});      
}

Therefore, it’s just a matter of binding this method to a button on my page to let the user save all of their deletes, inserts and updates:

<input type="button" data-bind='click: saveChanges' value='Save Changes' />

All that’s missing on the client is the code to run at startup to cause Knockout to bind my HTML to my ViewModel with its methods and collections. That code looks like this:

$(function () {
  ko.applyBindings(new PhvVM.SalesOrderVM());
});

A Breeze-Enabled Web API Service

See my earlier column for more details on creating a Breeze-enabled Web API service:

[BreezeController]
public class CustomerManagementController : ApiController
{
  EFContextProvider<SalesOrderContext> cm;

  public CustomerManagementController()
  {
    cm = new EFContextProvider<SalesOrderContext>();
  }

  [HttpGet]
  public string Metadata()
  {
    return cm.Metadata();
  }

  [HttpGet]
  public IQueryable<Customer> Customers()
  {
    return from cust in cm.Context.Customers
           orderby cust.LastName, cust.FirstName
           select cust;
  }

  [HttpPost]
  public SaveResult SaveChanges(JObject saveBundle)
  {
    return cm.SaveChanges(saveBundle);
  }
}

When you add Breeze to your project, it will add a BreezeWebAPIConfig class to your project that holds the Breeze routing rules for directing requests to your service.

That brings this column up-to-date with the current version of my ongoing TypeScript project. In my next column, I’m going to look at retrieving the child records associated with each Customer.