Search This Blog

2016-01-26

Express business language in your code with use cases

Brief Introduction to Use Cases

Use cases are a very important element in UML that addresses the functional aspect of a software. The use case diagram shows how the different system functionalities are associated to the different users in a system which are referred as actors.

The specific user kind is referred in UML as an actor. Note in the diagram above that a system can have several kinds of actors and an actor can be specialized from an existing one. For instance both Student and Teacher are specialized from School Member. This means they can also execute the same use cases from School Member which can serve to group common functionalities.

Also the objective of a use case is not just to describe a feature but to describe a business flow using a high level language that can be understood by the business expert on how a specific kind of user can achieve his goals.

For instance the "Enroll in Subject" use case can be described as follows:

====================================================
Project: My School System

Subdomain: Enrollment

Title:  Enroll in Subject

Description: Describes how a subject can be enrolled to a student.

Precondition: student must be authenticated by the system.

Normal Flow:
  • (n1) System lists all available subjects which were not enrolled or completed by this student
  • (n2) Student selects a subject
  • (n3) System verifies if the subject is open for enrollment
  • (n4) if subject is still open system enrolls student to it [a1]
  • (n5) System sends a message to the student stating that the enrollment was successful

Alternative Flows:

[a1] Subject is not open for enrollments: System sends a message to the user stating that the subject is not open for enrollment.

Integrity Constraints:
Student should not enroll in a subject he/she completed before.

====================================================

Use cases popular in the 90s and begining of 2000s almost disappeared after that and recently there has been some interest in it perhaps because software engineers have identified a need to better understand the business flow in more details than what can be found in use cases.

However use cases present many advantages such as:

  • Common language for engineers and domain experts - document can be the bridge between engineers and domain experts since it talks the language of the business in a structured way.
  • Technology independence - uses cases should not refer to specific technology in their descriptions such as web, http, button, dropdown, etc. - this way the contents continue to be useful even if those decisions change.
  • Enforces business flow - as described before the flow structure of use cases drive domain experts to think in a structured way and capture different situations helped also by engineers.

More details and better explanation can be found the links at the end in the References section.

However the point of this article is how to organize the software architecture and code style to reflect the business flow description provided by use cases.

Organizing Code Around Use Cases

The following practices can be taken to clearly express use cases in your code:

1) Represent each use case as a class
The use case diagram above can be translated with the following class diagram:


Each class represent a function in the system. Note that sometimes a use case may describe more than one scenario what can happen in CRUD functionalities such as Student Registration (which is not listed in our example diagram).

Note that the name of the class should match the use case.

2) Represent each use case flow step as a line of code
Code expression inside use case classes should reflect as much as possible the business flow description so to make it simpler and easier to correlate the documentation and code.

class UseCaseSubjectEnrollment
  def list_subjects(student)
    Subject.list_available_for_student(student) # (n1)
  end
  def enroll(student, subject)
    if subject.available_for_enrollment? # (n3) 
      student.enrolls(subject)           # (n4)
      { "type" => "success", "message" => "enrollment successful" } # (n5)
    else
      { "type" => "failure", "message" => "failed enrollment" } # (a1)
    end
  end
end

Note that the use case method is broken in two parts since one of the steps describes a user interaction: "Student selects a subject". The numbers in the use case and in the code above is optional and merely to make it clear for the reader to see the relation between them.

Before the user selection with list_subjects method and after the user selection with the enroll method. Due technological restrictions in web applications (at least in Ruby web applications) the user subject selection step is not represented in the use-case class but in the application layer presentation.

Pros and Cons of Use Case Mapping to Code

After some time using this approach for some years here are the positive and negative points:

Pros:

  • A change in a use case document can be easily implemented by software engineers 
  • Newcomers quickly understand how and where to do code modifications with little or no help
  • Engineers start work from the beginning with the business goal what reduces common misunderstanding in "what" the feature of functionality should be and its goals
  • Sometimes engineers can understand the business goal to the point of helping optimizing the business flow described by non-technical domain experts

Cons:

  • Includes one more step before engineers start developing software
  • There is a considerable effort to keep use cases updated 
  • Doesn't pay off for highly dynamic and small websites where the business flow is simple and already known by engineers
In general it seems to me that the more complex a system is in term of business steps the better it is to start using use cases.

References

[1] Writing effective use cases - Alistair Cockburn - http://alistair.cockburn.us/get/2465

[2] The art of writing use cases - Rebecca Wirfs-Brock - http://www.wirfs-brock.com/PDFs/Art_of_Writing_Use_Cases.pdf

[3] Domain driven design quickly - Abel Avram - Floyd Marinescu - http://www.infoq.com/minibooks/domain-driven-design-quickly

[4]    http://www.artima.com/articles/dci_vision.html - Trygve Reenskaug and James O. Coplien - The DCI Architecture: A New Vision of Object-Oriented Programming





2015-07-26

From static-language style API to Ruby style API

It has passed some time since I published a Naive_Bayes for text-classifier written in Ruby. At that time the API was designed very much influenced in way I have written a similar classifier in C++. However it was after a looked at the gem Decider that I realized how it was not taking advantage over the dynamic characteristics of Ruby to make Domain-Specific-Language APIs.

Static characteristics of my original Ruby classifier interface

The following are the methods that called my attention:

Category declaration

Use of add_category method to declare new categories expects a category name and an array of strings as an example.
classifier.add_category(name: :not_spam, training_set: [ 'Hi', 'Joe', 'how', 'are', 'you' ])

Input classification

The classify method makes use of an array of string as input for classification.
category = classifier.classify(['Hi','James','are','you', 'going'])
category.to_s # not_spam

Refactoring to new style

Category declaration through method missing and string

Instead of adding categories with a training set the user should only be required to provide examples to its desired with a dynamically created method which corresponds to a category name.
classifier.not_spam << "Hi Joe, how are you"

Input classification from string

Instead of requiring the user to break the string in an array the entire string can be classified. The classifier should also take the responsibility of breaking the string in words.
category = classifier.classify "Hi James,are you going ?"
category.to_s # not_spam

2015-01-26

Create an Agnostic Vendor Infrastructure in Ruby

Depending how the code was written adding new services to it can be difficult.
For instance, let's say we are building a rails application that gets integrated to cloud storage vendors.
A naive implementation would be to directly integrate to a cloud storage specific APIs.
In this case when new cloud storage vendors are added it is very probable that several nasty case... when ... end statements would be inserted in code.

When a new cloud storage service is added the developer must remember all places where those growing case-like statements are inserted. This makes the system more susceptible to errors due to  changes in several parts of the code. This problem is explained in detail by the shotgun surgery anti-pattern (http://en.wikipedia.org/wiki/Shotgun_surgery)

The rest of the system shouldn't be aware that a new cloudstorage service was added. That is where a combination of design patterns come in handy:
  • a facade to provide a simple interface for cloud storage operations 
  • a service locator to find the right cloud storage adapter
  • a cloud storage adapters that make each vendor API compliant to a single defined interface that can be understood by the facade


1) Cloud Storage Facade

2) Cloud Storage Adapter Locator

3) Cloud Storage Adapters

Note that this combination of patterns can be used to abstract many other types of services. Cloud storage service was just an example used here.

2013-12-18

Rails: New Framework - Old Design Problems

I have been programming for Rails for about 2-3 years now. As I came from a C# background it was a bit awkward for me to see some design principles I took as good practices being unashamedly broken such as:

  • data-driven models mixed with persistence logic instead of plain old domain objects
  • controllers being used as application scenarios instead of coordinators between my actual application object and the view ( that was my understanding of MVC )
At that time I just thought it was the ruby-on-rails way of doing things and as a good newcomer in the ruby developer community I decided I should learn and listen more from other rails developers and forums than telling what the best practices should be.

However after some years of work experience I realized some of those design problems were not sufficiently addressed for some anti-patterns: ( At least not until this year - some problems are still not addressed )
  • fat controllers / skinny models
  • skinny controllers / fat models
  • god models
  • transparent polyglot persistence in domain models ( SQL, NoSQL, Graph, etc ... )
Note that these design problems were solved in other programming environments long ago.

Now with the maturity of rails developer community and the increasing adoption of rails in many enterprises I see design patterns and ideas being presented more often. 
The objective of these ideas seems to be the same: keep active record models focused only on data and extracting out logic of any kind ( business, view, etc.. ) to other classes or modules.
Some ideas that called my attention are:
  • Use of service objects that orchestrate rails models in handling complex scenarios
  • Use of rails concerns (modules) to extract behavior or methods that do not belong to the model responsibility (which in rails means data persistence and validation)
Some oppose to rails concerns because it can lead your rails model class to have many roles instead of one-role. ( This is a popular clean code principle: one class, one role )
However in his article DHH gave good reasons for doing it what actually made me open an exception for this clean code principle for this particular ruby case. ( I am a clean code fan and exceptions are rare)

In this case this clean code principle of one-role-class became a bit different for me after reading DHH article (see reference below in chubby models): 
  • one class should have one IMPLEMENTATIONAL role. 
In Ruby a rails model should implement only ONE role while it can be injected by many others.
For instance it is not a problem that your class contain many roles since they come from mixins.
However mixins (or Rails concerns) should augment the rails model features and not make your class implementation dependent on them. It is not forbidden to be dependent on mixins such as by active record or mongoid since they are part of the one implementational role defined for the class but some caution is needed.

In the other hand the idea of using a service object can make it clear that some complex business concepts are executed separately. Scenarios include payment process, authentication and many others. Its benefit is very clear to me.

Both ideas are of great help to keep both controllers and models on a diet ( skinny controller / skinny models ) but other design problems such as transparent polyglot persistence and possible many others remain unanswered.

I hope to see what the ruby community will have to say about that in the future.
Maybe I can answer some of those questions, who knows ?

References:









2012-12-06

RORM - Ruby Domain Objects with Persistence

After some time using ActiveRecord and MongoId, I decided it was time to create a ruby ORM for domain objects as my first github project.
https://github.com/hcmarchezi/rorm/blob/master/README.md

2012-11-12

Separated Interface Design Pattern


When developing a system in many cases it is possible to identify dependencies among different layers whose responsibilities are well defined in the system.

Some examples of layer dependencies are:
  • Controller layer dependency and UI layer
  • Domain logic layer and persistence layer

One strategy to remove dependencies between layers is to use the separated interface design pattern. This pattern consists of defining an interface from the bottom layer that is going to be used by the top layer. See diagram below  to understand how it works for controller and UI layer:


The controllers in the example above only reference interface views and never know which view implementation they are actually working with.

This design pattern is recommended for a system when:
  • One layer (such as a controller) will be reused to be plugged into different versions of the other layer (such as HTML5 and native view layer implementations)
  • Layers are easier to be tested in isolation
  • It is not desired that one layer has API dependencies from the other layer

References:




2011-08-28

JavaScript: Object Oriented Programming

By using functions and the structures above it is possible to a function object which syntax works just like a C++/Java class. See examples below.

Classes

In JavaScript classes are declared as functions.
function Task(name,dueDate)
{
    this.name = name;
    this.dueDate = dueDate;
};
var myTask = new Task("Clean house","2011-07-01");
myTask.name = "some new name";

Methods

Methods are declared by extending the function prototype.
var User = function(email,password) {
    this.email = ""; // public field
    this.password = "";
};
User.prototype.generatePassword = function() {  // public method
    this.password = "generatedpass";
}
var user = new User("you@email.com","mypassword");
user.generatePassword(); // password is generatedpass
Alternatively methods can be declared inside the function declaration.
var User = function(email,password) {
    this.email = "";
    this.password = "";
    this.generatePassword = function() { 
        this.password = "generatedpass";
    };
};

Inheritance

In order to make a class inherit from another class, the subclass prototype must be set to the desired parent object. It is also necessary to set the constructor as the current class which is a little od. See example below.
function Person() {
    this.firstname = "James";
};
Person.prototype.generateName = function() {
    this.firstname = "generatedname";
};

function Student() {
    this.school = "Rahway School";
};
Student.prototype = new Person();
Student.prototype.constructor = Student;
Student.prototype.setBestSchool = function() {
    this.school = "Best school in town";
};

Polymorphism

Polymorphism can be achieved by simply declaring methods with the same name. Consider the hierarchy of figures as an example below.
function Photo() {    
}
Photo.prototype.getDestinationPath = function() { 
    return "./photos/common";
};
function PartyPhoto() {
}
PartyPhoto.prototype = new Photo();
PartyPhoto.prototype.constructor = PartyPhoto;
PartyPhoto.prototype.getDestinationPath = function() {
    return "./photos/parties";
};

photo = new Photo();
photo.getDestinationPath(); // path for common photos

partyPhoto = new PartyPhoto();
partyPhoto.getDestinationPath(); // path for party photos

Encapsulation

In the examples above all attributes and methods were public. In order to declare private attributes or methods one solution is to follow the template code below: (taken from http://www.codeproject.com/KB/scripting/jsoops.aspx )
function MyClass(){    
    //Private members
    return{
        //Public members
    }}
An App class can be implemented as:
function App(appname,description) {
    var _name = appname;
    var _description = description
    return {
        getName: function() { return _name; },
        getDescription: function() { return _description; },
        setName: function(appname) { _name = appname; },
        setDescription: function(description) { _description = description; }
    };    
}
var myApp = new App("voila","my game");
var.setName("other game");
Please note that this approach does not offer a way to have encapsulation and inheritance at the same time. Read next section to know one way to achieve this.

Inheritance with Encapsulation

By experimenting with the approach above, I found out a different way that made it possible to have both encapsulation and inheritance in JavaScript. The idea is to declare private members as function variables as above and then augment the parent object with the desired public functions. Thus it is not necessary to work with prototypes. Take the generic Person class as an example:
function Person(name) {
    // Private Members
    var _name = "";
    // Public Members (accesses private members)
    var obj = new Object();
    obj.setName = function(name) { _name = name; };
    obj.getName = function() { return _name;  };  
    // Constructor
    obj.setName(name);
    return obj;
};
A person instance will have access to getName and SetName but not _name attribute and therefore we have encapsulation. For a Student class that inherits from Person, the code would be:
function Student(name,school) {
    // Private Members
    var _school = "";
    // Creating parent object: Studen inherits from Person
    var parent = new Person(name);
    // Augmenting parent object with Student methods
    parent.setSchool = function(school) { _school = school; };
    parent.getSchool = function() { return _school; };
    // Constructor Logic (Initialization)
    parent.setSchool(school);
    return parent;
};
These functions can be used just like normal classes:
var person = new Person("James");
person._name; // undefined
person.getName(); // James

var student = new Student("Jack","Orange City School");
student._name;        // undefined
student.getName();  // Jack
student._school;       // undefined
student.getSchool(); // Orange City School