Breaking the Rules Part I: Create Quality Software the First Time

Break the Rule: You do not have time not to do it the right way the first time.

There seems to be some unwritten rule that you do not have time to do it right the first time. Break this rule now. You do not have time not to do it right the first time.

Let’s face it, there is always a business end to developing software. There is a need and addressing that need quickly makes a difference. Hopefully, the business end (management) has a plan or a product road map. It is called a road map for a reason – there is a starting point, a destination, and points of interest along the way. There may be short-cuts to your destination, but you still have a road to travel and a distance between here and there.

For this reason, you need to plan for a successful road trip. You will need to meet milestones and deliver software features, that is what you do and that is what makes you valuable. Since there will be a need for your services for this journey, doing it the right way the first time will allow you to continue and end the road trip successfully.

As a developer though, how many times have you seen a project that seemed perfect in the beginning turn out to be total chaos down the road? Why does this happen? It happens because it becomes more difficult to add new features and deliver on time as the source code becomes more complex. There was never a plan to handle the complexity that came later. There was never a plan in place to create consistent and maintainable code. There was never a plan to create unit tests to determine what is and what is not working – kind of like a dashboard on your car. The “Check Software Engine” light is on, but no one knows what to do.

Only a fool would start a road trip without checking the oil and tires. In real life, we do the right things because they are important. In software development, it should be the same way. I guarantee that doing it the right way the first time doesn’t take more time. You can deliver more features and deliver them on time. You will hit the milestones of the project. And the best benefit is that you will enjoy the journey along the way until you reach your destination. I have seen small and large teams do this. It is not impossible.

Here are five (5) ways to create quality software the first time.

  1. Create business logic using classes – create a framework, or use the Vergosity framework
  2. Implement business rules using a Business Rule Engine – create a rule engine, or use the Vergosity Business Rule engine.
  3. Implement unit testing early and throughout the development process. This is your safety net – kind of like road-side insurance.
  4. Implement logging for your application early.
  5. Use a well-defined architecture that includes proper abstraction between the layers of your application.

Vergosity Rule Engine + Fluent API

The Vergosity Rule Engine is now easier to use with Fluent API features. Basically, there is a ValidationContext object that  you can add and configure rules using fluent API style syntax. If you are not familiar with the ValidationContext – it is contained in the Vergosity.Validation namespace. And if you are not familiar with Vergosity, you can get from Nuget: Install-package Vergosity.Framework. Or search by “Vergosity” in your “Manage Nuget Packages” reference option.

image

ValidationContext

The Vergosity Rule Engine contains a set of rules already implemented. You can start by adding them to an instance of the ValidationContext. There are (2) ways to use the new Fluent API. You just need to create an instance of the ValidationContext.

ValidationContextBase context = new ValidationContext();

Simple

Option 1, shown below is the easiest way to add a new rule to the ValidationContext. All of the new Fluent API calls are prefixed using “With”. This provides a nice filter for your methods. Below, an entity is setup for the unit test and is used as the target parameter in the IsNotNull rule.

image

When you call the RenderRules() method of the ValidationContext – you can retrieve the results from the Results list. You can use the results any way you prefer in your application. The ValidationContext also contains results filtered by the Severity indicated in the rule configuration.

  • ValidationContext.ExceptionResults;
  • ValidationContext.InformationResults;
  • ValidationContext.WarningResults;

image

With Configuration

The unit test below shows another option that includes rule configuration – this is where the fluent api really helps out. After you add the rule to the ValidationContext, you are ready to start configuring the specified rule using a set of methods that are prefixed by “With”.

image

Custom Business Rules

There will be situations where you need to create a custom business rules. The Vergosity Framework contains the framework classes for you to create simple or complex rules. We will show you how to create these rules – and then use them in your code.

Simple Rule

Simple rules inherit from the Vergosity Framework class called Rule. You modify the constructor to send in your target. The Render() method is where you implement the rule’s validation logic. You will need set the IsValid property to true/false based on the rule logic – then, you will return a new Result object as show below.

Simple rules allow you create rules that can be used or composed into composite rules. The rule rendering using the ValidationContext is consistent whether the rule is a simple or composite rule. Therefore, you have a lot of flexibility in managing business rules for you business logic.

image

Composite Rule

You can create a custom rule that contains any of the default rules and/or other custom rules. This allows you to compose your custom rule to contain whatever rule-set you require for you business logic. The composite rule will inherit from the Vergosity Framework class called: RuleComposite. Creating a custom rule allows you to reuse the rule from one or more locations in your code. You are also encapsulating the rule implementation into a single rule – therefore, you will only have one place to modify or extend you rule implementation.

Building the rule set is similar to the previous example in the unit tests. However, in the actual rule, you use the Rules list to add rules.

image

The following is the code snippet from the composite rule class. If you have noticed the WithPriority setting, this allows you to set or arrange the order that the rules are evaluated.

this.Rules.WithStringIsNotEmptySpace(entity.Name)
    .WithName(“NameIsValid”)
    .WithMessage(“The name value is not valid.”)
    .WithPriority(100)
    .WithSeverity(Severity.Exception);

this.Rules.WithAreNotEqual(entity.DateOfBirth, new DateTime())
    .WithName(“DateIsInitialized”)
    .WithMessage(“Date contains the default DateTime value.”)
    .WithPriority(200)
    .WithSeverity(Severity.Exception);

this.Rules.WithRange(entity.FavoriteNumber, 1, 100)
    .WithName(“FavoriteNumberIsValid”)
    .WithMessage(string.Format(“The favorite number value is not within the specified range: {0}-{1}”, 1, 100))
    .WithPriority(300)
    .WithSeverity(Severity.Information);

this.Rules.WithGuidIsValid(entity.Id)
    .WithName(“IdIsValid”)
    .WithMessage(“The entity id is not valid. Cannot be empty Guid value.”);

Code Generation :: Vergosity, Razor Engine & Entity Framework

I recently created a Code Generation tool that targets a set of entity items in a .NET project – to generate an entire .NET stack that includes a Service, Business and Data Access Layers. Because Entity Framework has database migration tools I can leverage my Entity Framework DbContext (that is generated) to also create a database based on the specified DbContext. I can do this in less than 10 minutes. I think that is productive, right?

The application leverages the Vergosity Framework and a light-weight enterprise architecture. I felt that once I had the architecture in place and realized the patterns were repeatable, I was ready for code generation. It has been a few years since I have worked with a code generator. The first consideration of code generation is to define the source that will be used to generate code. The second consideration are the templates. Then you bind the source with the template to create the output. Sounds pretty straight forward. You have some binding options when you are using .NET (i.e., T4Templates, Razor Engine). I chose the Razor Engine because this allowed me to use Razor syntax in Visual Studio to create my templates (.cshtml) files – this turned out to be the easiest part of creating the code generator. I’ve worked with T4Templates in the past. I do not have anything against them, just wanted to try something different.

Try it out for yourself…You can get the installer on GitHub (https://github.com/buildmotion/CodeBuilder-Install) or you can download the actual source code and see how it works.

Download the BuildMotion.CodeBuilder

You will need to get the source code which is contained in (2) projects on GitHub. The CodeBuilder requires a reference to Vergosity.Services and to the latest version of the Vergosity Framework (available on NuGet).

Here is a screen shot of the main window for the Code Builder. It was built using WPF on top of the Vergosity Framework for handling all of the business actions. The application doesn’t use a database, although I could see some future feature that saves the configuration.

image

Recipe for the Application

I would recommend starting out with a new or existing C# .NET Class Library project. You will want to make some NuGet package references.

1. Reference the Vergosity Framework & Vergosity.Services

You can reference the Vergosity framework with one of (2) ways using NuGet.

Package Manager Console: Install-Package Vergosity.Framework

URL: https://www.nuget.org/packages/Vergosity.Framework

The Vergosity.Services source code and project is located on GitHub. You will need to reference this project for both the BuildMotion.CodeBuilder and your target application.

GitHub: https://github.com/buildmotion/Vergosity.Services

2. Create or Modify Existing Entity

You will want to create or modify your entity classes. Make sure your entity classes inherit from Vergosity.Entity.IEntity or some other distinct interface. You might need to create one for you entity classes. This will be used by the code generator to target all classes in your project that implement or inherit from the specified type.

Ex: public class Customer : Vergosity.Entity.IEntity

image

3. Add Identifier Properties to your Entities

Make sure your entity have identifier properties. If you are using the Vergosity.Entity.IEntity interface – you will need to implement the Id property as a System.Guid.

4. Add reference to the DataAnnotations namespace

We are going to use some annotations to provide information to Entity Framework Migrations when we generate the database from the code. Pretty cool, right. Now, Entity Framework will know which property is our identity column.

Reference: System.ComponentModel.DataAnnotations

image

5. Compile the Target Assembly

You will now want to compile the target assembly project before you generate your code. You will select the actual compiled assembly when you use the BuildMotion.CodeBuilder tool.

image

6. Open/Run the BuildMotion.CodeBuilder application.

  1. Select the target assembly. It should be compiled with your Entity definitions.
  2. Enter the default or core namespace for the application. (i.e., BuildMotion.Reference)
  3. Enter the Application Name (i.e., ReferenceApp).

image

7. Build Some Code

This will provide the CodeBuilder enough information to create the Service and Entity Framework code. It will also create a few other necessary files for the application. For example, I use Autofac as the dependency injection container, and there is a bootstrap class to do the initial wire up.

  1. Click on the Build Service Code button.
  2. Click on the Build Entity Framework Code button.

image

8. Create Entity Code: Service, Business, Rules, Validation, and Data Access Repositories.

  1. Click the Retrieve Entity Items button.
  2. Select one ore more entity items to build your code.
  3. Click the Build Code button to finish generating all of the code.

image

If you are all good, you will the following.

image

9. Include the code into your Target Project.

You will now want to include all of the generated code into your project and compile when you are ready.

image

ASP.NET Web API

I’m starting a new project that will be using ASP.NET Web API. I have used WCF in the past to create RESTful services – so I’m very interested in how I can achieve the same using Web API. It relies on the HTTP methods:

  • Get (retrieves a list of items)
  • Get (retrieves an item by id)
  • Post (creates a new item)
  • Put (updates an item)
  • Delete (removes an item)

So, if I am working with a Customer entity, I would have the following web api:

  • // GET api/Customers –> public List<Customer> Get(){..}
  • // GET api/Customers/123 –> public Customer Get(in id){..}
  • // POST api/Customers –> public void Post(Customer c){..}
  • // PUT api/Customers/123 –> public void Put(int id, Customer c){..}
  • // DELETE api/Customers/123 public void Delete(int id){..}

API Method Names

Notice that the method names correspond to the HTTP Method type. This is by convention. However, you have another option by convention as well, you can prefix the methods with the HTTP Method type name. You can use the same URI and ASP.NET Web API will know which method to call in the CustomersController.

  • // GET api/Customers –> public List<Customer> GetAllCustomers(){..}
  • // GET api/Customers/123 –> public Customer GetCustomer(in id){..}
  • // POST api/Customers –> public void PostCustomer(Customer c){..}
  • // PUT api/Customers/123 –> public void PutCustomer(int id, Customer c){..}
  • // DELETE api/Customers/123 public void DeleteCustomer(int id){..}

You can also modify the default convention by using Web API attributes. Using our GET as an example, we can use the default Get() method, or we can

  1. Use the default: Get()
  2. Prefix the method name with the HTTP Method: GetCustomers()
  3. Use the [HttpGet] attribute and name the method whatever we want.
  4. Use the [AcceptVerbs(“GET”)] attribute and also name the method whatever we want.

// GET api/values
//1. public List<Customer> Get()
//2. public List<Customer> GetCustomers
//3. [HttpGet]
//public List<Customer> GetAllllllCustomerss()
// 4. Use [AcceptVerbs(..)]
[AcceptVerbs(“GET”)]
public List<Customer> GetAllllllCustomersWithAcceptVerbs(){..}

As we can see, the mapping the actual URI to the Controller’s method is flexible. Each of the implementations noted above will return the same result. There is also another option to configure the mapping of the URIs to the Controller methods – this is an RPC style, where you actually include the name of the method in the URI – this requires you to modify the HttpRoutes to include the name of the Action in the URI. It is an option – however, I’m going to stick with the more conventional approach.

API Routing

Really, both approaches use Routing. You can modify the route map and register the new route by modifying the WebApiConfig class. If you wanted to use the RPC style (with the Action name), you would just update the RouteTemplate with “api/{Controller}/{Action}/{id}”.

imageC

There may be other parameters to put into the route template. For example, in a multi-tenant application, you might include an additional parameter and provide a constraint for the value.

image

Http-Compliant ASP.NET Web API

There are specific things that you will want to do to keep you API Http-Compliant. This is a good thing. We want users of the API to understand the API and have certain expectations when they are working with it. We’ll talk about the message body, Request and Response, and Http status codes.

When we are working with Http Methods what we return in the response and what status codes we use matters. For example, using our simple Get() method – the following implementation is fairly naïve. We are not returning any status codes in the response. The id value supplied may not even be a valid Customer identifier. So we have to be concerned with the how we handle the response and what status codes we use.

image

An improvement would be to provide a response and a status code if the specified item was not found. Otherwise, the status code would 200 OK.

image

When the request for a Get is valid, I get the XML in the response and the status code is 200 – OK.

image

When I inspect the HTTP request and response in Fiddler, I see the expected status code.

image

Let’s see if I get the 422 status code when the customer is not found during the request. I not only get the correct status code when I do not find the customer, but the Reason Phrase value is also provided in the response. This information will help users of you API to understand the responses when they do not get the expected results. In a more comprehensive solution, we would want to provide other status codes to indicate other causes of not providing the expected response: 200 OK.

image

Create a new Resource using the Web API

Just as there is special handling in processing a GET request, there is a protocol to use when creating a new resource using HTTP POST. The information used to create a new resource is contained in the body of the Http Request. The data or information can be either XML or JSON format – it just needs to represent the target we are trying to create. The response is also different – we not only need to return a status code, but we need to include some details about the new item that was created. This includes a URI to retrieve the item that was just created.

To improve the ASP.NET Web API default Post method – we update the return type to HttpResponseMessage. This will allow to provide a nice response with a status code, the resource just created, and a URI that will allow the user of the API to retrieve the item just created.

image

To make the request, we need to create the information used in the body of the request:

{“Name”:”Maria”}

I’ll use Fiddler to compose a request.I updated the body with the JSON that represents a new Customer, I changed the Http Method to POST and updated the URL.

image

When I execute the request using Fiddler, I expect to receive the information described above. I get the 201 Status – Created and the JSON data in the content represents my new Customer.

image

Conclusion

We covered a little bit of ground in setting up a GET and a POST. I’ll continue later with a blog entry about PUT and DELETE. But so far, we see how we can use Fiddler to generate a request and/or replay a request. We can retrieve data from our application using HTTP method calls – which has so many uses.

ASP.NET Identity Security

The new ASP.NET Identity framework provides membership features for your application – well kind of. Compared to the previous membership providers there appears to be not much there. However, do not be fooled. Although, many of the typical membership method calls just don’t’ exist, this new membership implementation is very extensible – which allows you the developer to customize the implementation to your specific needs. You can use SQL Server as your data store, but there are a lot more options now, especially the integration with other social platforms. This ain’t your dad’s membership provider.

Typically, you would create an ASP.NET MVC web application and implement the new ASP.NET Identity within the web application – this means making calls directly from the controllers to the database using the new Entity Framework IdentityDbContext<IdentityUser>. I think for most demos and simple applications this may work fine. However, I like a little more abstraction between the UI, business, and data access “parts” of my application. Therefore, since this new version doesn’t have any dependencies on any web assemblies – I can implement and customize my security in a separate class library.

I start by creating a new C# Class Library project and add the required packages from NuGet to support my custom implementation of AspNet.Identity.

https://www.nuget.org/packages/Microsoft.AspNet.Identity.EntityFramework/1.0.0

image

The NuGet installer also installs other required packages for Identity.

image

IdentityUser :: The ApplicationUser

I start by creating a new entity called ApplicationUser. This entity implements the IdentityUser interface from the Microsoft.AspNet.Identity.EntityFramework namespace. You will need to reference the namespace with a using statement.

image

The IdentityUser interface is shown below with its implementation of the IUser interface – these interfaces provide the default structure for the new user in the Identity framework.

image

image

It is interesting to note that the Id property is a string type. The value stored in the database from the Identity framework looks like a GUID – it is the string representation of a GUID value. It appears that you would have to re-implement the IUser interface and the IUserStore of the Identity framework to make a change to an Id property using an int. I’m not sure if I’m ready to tackle this task yet. I’m trying to leverage as much as possible from the default implementation. See StackOverflow.

UserManager

The AccountController creates an instance of the UserManager<TUser> through its constructor. This class provides all of the methods to manage a specific user via the ApplicationUser class. When the UserManager is created it requires a new UserStore<TUser> where TUser is of type IdentityUser. The UserStore object requires an instance of the IdentityDbContext<TUser>. I would consider the UserStore as the “repository” that uses Entity Framework for database transactions since it depends on the IdentityDbContext. The UserManager is the business end of the managing users. You can imagine that this is where additional data validation and business rules are implemented before making a call to the database using the UserStore<ApplicationUser>, right?

This is why the ApplicationUser entity is so important. It is used to create generic implementations of the UserManager, UserStore, and IdentityDbContext. In the code below, I’m beginning to refactor the Register() method to use the entity defined in my custom project, I will then implement the CreateUser() call using my new SecurityService (code currently commented out).

image

Enterprise Patterns :: Vergosity Framework

I have quite a bit of infrastructure setup already complete using the Vergosity Framework that includes: Business Actions for implementing business logic and the rule engine to take of processing my data validation and business rules. I’m also experimenting with a new set of pattern that take advantage of dependency injection. Therefore, I’m relying a lot on the Autofac DI container to do this for me. The framework also includes Logging of an application error or failed business rule evaluations.

This implementation confirms to me that I can abstract the ASP.NET Identity references from my ASP.NET MVC web application and put the implementation into a new project – this will allow me to reuse the new implementation in other applications.

Code First without dropping the database

I have been using the Entity Framework code first options for a prototype application architecture. I have the database initializer setup called from my unit tests to validate the integration work I’m doing. This is working fine for me now. However, in most enterprise applications the developer would not be responsible for generating the database – much less dropping and re-creating the database and all of the table objects.

Therefore, I’m going to change the approach a little bit. I still want to do code first in terms of setting up my entity classes. However, I want a little more flexibility in working in a team environment where there is a dedicated DBA who is responsible for managing the database objects. The sample database that I’m using for the code first EF contains a table called EdmMetadata. I’m going to remove this table from the database – so that it is not used as part of the initialization. This means my database will not be dropped when the initializer is called.

image

image

I will also remove the call from my unit test Setup() method.

image

The unit test runs and passes – this is good news. Now I do not have the dependency on the database initialization process.

image

Now, I’d like to add a new entity item that maps to a new table in my database. I can define the entity first and create the table object later. You might be wondering why I’m not using the EF tooling. My data access doesn’t contain an .edmx file – I am using a generic Entity Framework Repository<T> pattern with the future possibilities of code generating the plumbing classes later using the entity class as a meta file for the code generator.

New Entity and Database Table

I am now creating a new entity with a matching table in the database.

image

The Coder entity uses a base class for default entity behavior and implements the IEntity interface – which means that there must be an Id property for the entity.

image

Generic Entity Framework Repository

I have some infrastructure repository classes that provide the default implementation of the EF calls for a specified entity. To do the wire-up, I create an interface called ICoderRepository that implements the IRepository<T> class. This will allow me to add an extended behavior not already contained or implemented in the generic repository classes. I also create a CoderRepository class which is the concrete implementation for the Coder entity’s repository. It implements the GenericRepository<T>

image

I do have a DbContext class that the generic repository is using for data access. I just need to let it know about the new entity that I have created. Therefore, I create a partial class for my context CodeDb and add the DbSet<Coder> public property. Note: the name of the DbSet<Coder> property should match the name of the database table – if your database table has a different name, I am sure you can just attribute the table name on the entity itself.

image

Now my CodeDb context will know about my new entity and will be able to perform data access.

image

So, if you are keeping track, we have added (2) classes and (1) interface to implement the EF Repository for the Coder entity. Using this approach will allow me to later generate these plumbing classes and wire-up entity repositories with ease. But without the code generator, it still isn’t that much wire-up. I like the convenience of the Generic Repository and the partial classes to add to the core infrastructure of the DbContext and Repositories. Now that the repository is configured, I can create another partial class that will enable access to the repository from business logic classes. There is no .edmx file to manage or now specialized EF connection strings – we can just use a standard connection string name (note: I send in the name of the connection string only) in the configuration file and the DbContext constructor does the rest.

image

The Wire-Up using Dependency Injection

Now for really cool part. It is all wired-up using dependency injection. The DI container will scan the assembly for specific repository implementations and initialize the concrete repositories during runtime.

My business object BusinessProvider contains the injected repository CoderRepository – with the ability to use the GenericRepository methods to add the entity to the corresponding database table.

image

I run my unit test and everything is good – the data made it into the database.

image

image

Conclusion

So, after creating the entity, I added some partial classes to onboard the entity into the generic repository and the DbContext – I consider this plumbing/infrastructure code. Then I added another partial class to add the CoderRepository reference to the BusinessProvider business class. Then with a single method call, no additional coding required, I was able to perform the data transaction to the specified database.

The implementation details only took a few minutes to setup. There is definitely a recipe here to make sure that all of the infrastructure classes are setup. These are there primarily for extensibility in the case you need to add some specialized behavior that is not already implemented in the generic repository. I like the approach of having a single repository for each entity in your solution. Using the partial classes enables that. What I didn’t include in this post is how the Generic Repository<T> works and how dependency injection is used to perform the wire-up.

Vergosity Business Actions

What are business actions? They are simple units of business logic implemented using the Action base class from the Vergosity Framework. They are just simple classes that follow a specific pattern. All of the business logic is performed in the PerformAction() method. Notice that the constructor takes in the target entity CodeSample. The entity value is contained in a field called _codeSample – which is decorated with a rule attribute EntityIsValid. This rule is evaluated when the action is executed. If any of the business rules and data validation rules fail, the PerformAction() method is not called or processed. You can supply the action with as many input items as you wish. This action takes the input parameters in the constructor – however, there isn’t anything preventing you from adding public properties to do the same.

This action has an output object, the IsUpdated boolean property. Since we are using classes for the business logic implementation, we are not limited to a single return or output item. We can have as many as we need. Using classes to implement business logic has a lot of benefits.

image

Most of the magic of the business action is implemented in the ActionBase or more so in the framework Action class. The following shows the base action class which is a generic. It contains the common or shared elements of the business action and inherits from the Vergosity Framework Action class which is abstract. This base class contains a ProviderBase class which coordinates calls to other business actions within the specified service.

image

Vergosity Framework :: Action Class

The Action class provides the structure or processing pipeline for the business logic implementation.

image

The action process is started by calling the Execute() method. This is the implementation of the Template Method pattern. There is a series of things that happen before and after the execution of the actual business logic. And as you can see from the diagram above, if you want to include any additional behavior – there are several events that you can hook into to add your own custom features.

If everything goes well, meaning that the user is authorized via permissions and no business rules or data validations have been evaluated false – the call to the ProcessAction() is made. This is where the actual business logic is implemented or what you define as the action to perform.

image

There is a lot more going on in the StartAction() and the FinishAction() method calls – but for now just understand that there is a pipeline of processing for the execution of a business action. If you use business actions to implement all of your business logic, you have a very consistently mechanism for managing the process. Adding new behavior or features globally (to all business actions/logic items) is very easy using the base classes.

How Business Actions Are Called

You might be wondering how business actions are called. They are simply initialized as any class would be and started by using the Execute() method. The following example is more advanced because it is using Dependency Injection – but the approach is the same:

1. Initialize the action and pass in the parameters to the constructor.

2. Execute the action.

3. Retrieve the return object of the action.

image

You do not have to use Dependency Injection, however, the sample application I’m using demonstrates an architecture that takes advantage of DI techniques. The DI container is resolving the ActionManager<T> – a generic class. This generic type is injected with a BusinessProvider instance that is injected with a one or more Repository items used for data operations. There is a lot of opportunity to remove dependencies from your application objects by using DI. What we see in the ActionManager<T>.Execute() method is the actual call to the business action’s Execute() method. Using DI allows for more extensibility of my implementation of business logic. I can control how my business logic is wrapped and called – without effecting the actual implementation of the business logic. .

image

Conclusion

Using a class-based approach to implement units of business logic has many benefits. The implementation is very consistent and maintainable. Extending or adding new behavior is much easier using the base classes and/or using depending injection. Since each action class is a specific unit of business logic – there is a lot of opportunity to perform unit testing and perhaps using a test-driven approach to the implementation of the business logic.

The Action part of the Vergosity Framework is even more powerful when you combine it with the power of the business and data validation rule engine. Decorating your target objects with rule attributes is simple and easy.