Why do we consider immutable objects?
The biggest problem of enterprise software is the complexity of the code. Readability - is perhaps one of the most important aspects of programming. And you should try to ensure that your code was laconic. Code written without considering this factor, it is very difficult to analyze and check for correctness.
Let's look at an example:
// Create a search criteria
var queryObject = new QueryObject <Customer> (name, page: 0, pageSize: 10);
// We are looking for customers
IReadOnlyCollection <Customer> customers = Search (queryObject);
// Adjust the criteria if one is not found
if (customers.Count == 0)
{
AdjustSearchCriteria (queryObject, name);
// Will not here queryObject?
Search (queryObject);
}
Is the request object is changed to the point where we do a second search? Maybe yes. And maybe not. It depends on whether we find anything, having carried out the first search. And also on whether the search criteria will change after the method AdjustSearchCriteria. Simply put, we can not know in advance whether the change request object in the second search.
Now consider the following code:
// Create a search criteria
var queryObject = new QueryObject <Customer> (name, page: 0, pageSize: 10);
// We are looking for customers
IReadOnlyCollection <Customer> customers = Search (queryObject);
if (customers.Count == 0)
{
// Adjust the criteria if one is not found
QueryObject <Customer> newQueryObject = AdjustSearchCriteria (queryObject, name);
Search (newQueryObject);
}
Here once everything is clear: after we have found nothing in the first search method AdjustSearchCriteria create new criteria, which in turn will be used in the second search.
So, what are the challenges in working with data structures undergo changes?
It is difficult to estimate the written code, if we can not be sure whether to modify certain data or not.
It is difficult to follow the numerous references, if you took a look at not only the method but also to functions that are called in this method.
If you are writing a multithreaded application, the tracing and debugging code becomes even more complicated.
How to describe immutable objects?
If you have a relatively simple class, then you always have to consider whether to make it the same. It is generally correlated with the concept of Value Objects - they are simple and easy to do the same.
So how do we describe immutable objects? Let's look at an example: we have a class ProductPile, representing some of the products that we put up for sale:
public class ProductPile
{
public string ProductName { get; set; }
public int Amount { get; set; }
public decimal Price { get; set; }
}
To make a class field ProductPile unchanged, we will mark them as read-only, and will create a constructor:
public class ProductPile
{
public string ProductName { get; private set; }
public int Amount { get; private set; }
public decimal Price { get; private set; }
public ProductPile(string productName, int amount, decimal price)
{
Contracts.Require(!string.IsNullOrWhiteSpace(productName));
Contracts.Require(amount >= 0);
Contracts.Require(price > 0);
ProductName = productName;
Amount = amount;
Price = price;
}
public ProductPile SubtractOne()
{
return new ProductPile(ProductName, Amount – 1, Price);
}
}
So, what we have achieved such an organization of class?
Now we can not worry about the correctness of the data - check the value we only once in the constructor.
We are absolutely sure that the values of the objects are always correct.
The objects are automatically thread-safe.
Increased readability, as now there is no need to check whether the values have not changed objects.
Restrictions on use
Of course, everything has its price. We can apply our idea in the small and ordinary classes, but it is not applicable to the majority.
First of all, it is worth noting the performance. If your facility is large enough it turns out, the creation of copies each time you change some parameter is not the best impact on application performance.
A good example here is the constant collection (immutable collections). The authors took into account performance issues, and add a class Builder, which allows you to "mutrirovat" change the collection:
var builder = ImmutableList.CreateBuilder <string> ();
builder.Add ("1"); // Add a string to an existing object
ImmutableList <string> list = builder.ToImmutable ();
ImmutableList <string> list2 = list.Add ("2"); // Create an object with 2 lines
Also, you will encounter a lot of problems if you try to make the volatile nature of the class intact. But do not let that stop you.
Conclusion
Consider the pros and cons of translation facilities to the same class, evaluate the costs and do not forget to think clearly. In most cases, you get the benefit (of course, if your class is small enough and simple).
0 коммент.:
Post a Comment