Sometimes I have problems with my own code. I wrote a piece of code. Some months later, when I wanted to use them in other places, I had to look at their implementation. Other time, I had to dig deeply into my poor memory to find out why I wrote them.
Obviously, there is a need to improve the code quality__the communication. What? Code communicates?
I like to see code in this way
Code is a mean of communication.
When we write a piece of code, either a framework, a library, a class, a method, or even a line of code; it supplies a mean of communication between us and
- Compiler: We tell the compiler what and how to translate into binary code.
- Computer: The binary code will then instruct the computer does our business logic (our purposes)
- Developers: They consume our code, our API
The code does more than our initial thoughts.
Let’s improve our communication mean. A long road starts with the first step. Let’s start with improving constructor.
Note: I write in the context of C# (.NET) environment. You should find similar concepts in yours.
Constructor
As a developer, we have seen this code a lot
/// <summary> /// A person with Name and Assigned To /// </summary> public class Person { /// <summary> /// Person name /// </summary> public string Name { get; set; } /// <summary> /// Assigned to (such as project name, task name). /// </summary> public string AssignedTo { get; set; } public Person() { } public Person(string name, string assignedTo) { this.Name = name; this.AssignedTo = assignedTo; } }
A very simple person class. Assuming that I want to use it in Project/Task
public class Project { public string Name { get; set; } public IList<Person> People { get; set; } public void AddPerson(string name) { var person = new Person { Name = name, AssignedTo = this.Name }; People.Add(person); } } public class Task { public string Name { get; set; } public Person Responsible { get; set; } public void AssignTo(string person) { var responsible = new Person { Name = person, AssignedTo = this.Name }; Responsible = responsible; } }
A person is used for people involved in a project. And it is used as a responsible for a task.
So far so good. The Person class has 2 constructors to use. However, if we look a bit deeper, there is a small issue that I usually call
It does not communicate its purposes well.
How do you know what purposes, under what context the object is created for?
Static Factory Method
How about creating an object with a clear purpose? What do you think about this code?
/// <summary> /// A person with Name and Assigned To /// </summary> public class Person { /// <summary> /// Person name /// </summary> public string Name { get; set; } /// <summary> /// Assigned to (such as project name, task name). /// </summary> public string AssignedTo { get; set; } public Person() { } public Person(string name, string assignedTo) { this.Name = name; this.AssignedTo = assignedTo; } public static Person CreatePersonOnProject(string person, string project) { return new Person(person, project); } public static Person CreateTaskResponsible(string person, string task) { return new Person(person, task); } } public class Project { public string Name { get; set; } public IList<Person> People { get; set; } public void AddPerson(string name) { People.Add(Person.CreatePersonOnProject(name, this.Name)); } } public class Task { public string Name { get; set; } public Person Responsible { get; set; } public void AssignTo(string person) { Responsible = Person.CreateTaskResponsible(person, this.Name); } }
There are 2 explicit static factory methods:
- CreatePersonOnProject
- CreateTaskResponsible
Can you read the code again in Project.AddPerson and Task.AssignTo methods?
On the implementation side, we have not changed anything at all. We construct the same object in both cases. However, we have gained a huge benefit: Communicate the purpose explicitly.
- Construct a new object (same as new approach)
- Communicate exactly the purpose.
- Consumers can use the code without confusion.
Which one should you choose? Both. As a developer, we should choose our tools wisely.
What should we do to improve our decision (decide when to use what)? One of a trick I usually use is that I ask this question
What do the other guys think? Is it clear for them to consume my code?
If the answer is “No”; no, they have to read my code to understand and use it; I will choose “Static Factory Method” approach.
There is no perfect code. But we can improve it over the time. When time comes, you will say thank you to yourself; other developers will say thank you to you.
You might find these posts interesting:
And since you made 2 static factory methods, the constructors they call should have been private
Yes. Good catch! It should be private or at least protected. However, I want to keep it public to prove a point: It is an improvement. There are cases that you might want to use constructors. If in a real project, product code, I agree we should try to avoid public constructor as much as we can.
Why there is a parameterless constructor 😛
There should not in production code. However, I have seen so many code that has public parameterless constructor 🙁 That is a bad habit because it is so easy to end up with invalid state object.