Start slowly to finish fast

“In programming, the hard part isn’t solving problems, but deciding what problems to solve.” – Paul Graham

I am fortunate enough to work with new, genius, competitive developers who have fresh perspectives. They often talk about faster algorithms, data structures, new-generation technologies, and buzzwords in the software industries. They are eager, motivated and wanted to change the world!

However, I did not hear from them about problem-solving using object-oriented analysis and design.

Some people try to solve the problem by directly jumping into programming solution without doing an analysis. They believe in trial and error methods. It’s like solving problems without knowing what problems to solve.

The well-proven OOAD techniques are there for decades, It’s a very beneficial technique for problem-solving. They will help you to know what problems to solve.

We should focus on what problems to solve rather than just writing the code.

IMO, we should start slowly to finish fast. What I mean here is, we have a problem at hand, divide it into three parts: Analysis, Design, and Programming.

These three are related terms.

The object-oriented analysis is meant for understanding the customer problem. Write use cases to capture what is needed and what is not. You can write lightweight use cases. Thus, you’ll focus on what is needed than trial and errors.

Benefits of writing use cases!

The next step would be the object-oriented design which emphasizes on designing the conceptual models i.e. classes to achieve the various use cases.

This classes will have attributes and behaviors. They interact with each other to solve the problem.

Try using outside in approach, class diagrams, sequence diagrams. You could use the whiteboard to evolve your conceptual design that tries to solve the customer problem.

Object-oriented thinking, the big picture!

Then comes the programming phase. Now you know “what part” of the problem and conceptual models, you can focus on how part i.e. coding.

The good analysis and design would help you to understand problems to solve, prepare good conceptual models, that intern leads you to good programming solution for the problem at hand.

Remember, don’t directly start coding without understanding the problem to solve.

Instead, use object-oriented analysis and design.

Start slowly to finish fast.

Object oriented thinking, the big picture

I see my recently graduated friends solves consumer problem by the procedural way (writing everything in a single class or a method) using object-oriented programming language.

In this post, I am sharing what and how I think while solving the consumer problem, The object-oriented thinking!

IMO, as an object-oriented designer, I divide the big problem into smaller ones. I provide the solution for small problems (concerns) using objects. Eventually, these objects communicate with each other by sending messages to solve the consumer’s big problem.

Let me explain it with the help of the use case. (We will consider the server-side solution)

Problem statement:

As the new user of the system, I want to register a user account.

We would consider only two fields on the user registration page, Name, and Email and sign up button.

Use case:

User can create his/her account

  • As a user, I navigate to the registration page.
  • Enter name and email.
  • Choose to register.
  • The user account is created.
  • Email is sent to the recipient.

The user cannot create an account when a name is not provided.

The user cannot create an account when email is not provided.

Solution:

As a developer, I need to provide the solution for these use cases. (I know there could be many alternate cases, however, let’s keep it simple.)

Clearly, there are different concerns that need to be addressed.

IMO, we need a class:

  • To validate the user inputs.
  • To create a record in a database.
  • To generate email content.
  • To send user registration email.

Thus, I would divide the concerns into

  • UserValidator class that validates user inputs and gives an error for validation rules like the name is required, email is required and so on.
  • UserRepository class that takes user entity and insert records into the database.
  • EmailTemplate class that generates the email content.
  • EmailSender class that takes email content and sends the email to the recipients.

UserController class that does the following stuff and try to solve the big problem by sending messages to the object of the above classes.

  • Verify the user inputs.
  • Create a user in the database.
  • Get registration email content.
  • Send registration email.

Note: To convey the intent, I kept this design as simple as possible. We could give more clean solutions like outsourcing the responsibilities of the controller (Keep controllers as thin as possible) to model classes and so on. Please feel free to share your feedback with me.

You can observe, The proper object-oriented design would divide the big problem into the smaller ones across classes. Solve small problems in order to solve the bigger one.

https://blog.beingcraftsman.com/datta/

How writing use cases can help you

During my initial career in software development, I was directly jumping to a programming solution without doing problem analysis.

I still remember sometimes I had missed some of the functionalities since I haven’t done the proper analysis.

I and my product owner were having too many discussions.

When I worked with the education team in Tieto, I got the habit of analyzing customer problems. During analysis, I choose to divide the customer problem i.e. requirements into use cases.

I choose to share it with my product owner before starting the coding. 

Since then I have been writing the use cases before starting the coding, why? See these benefits.

  • You could anticipate whether estimation assigned to a story/work item is correct or not and can raise the flag within the team.
  • You could easily break down the work into the small minimum viable product.
  • You could get better ideas about use flows like instead using a button in grid row, we could use a toggle button.
  • You could create a happy path, unhappy path, edge cases, and alternative flows so that you would not miss any cases or functionalities.
  • You could easily track the progress of the story/work item.
  • You could give clear updates in daily standups as I worked on use case#1 yesterday and today will finish use cases# 2 and 3.
  • You could anticipate the code changes in advance against all cases.
  • You could anticipate the blocking dependencies say for example you’ll need an answer from the product owner.
  • As a developer, it would help you to write tests against these use cases.
  • As developer/QA/PO, you could do functional testing against the use cases.

I would recommend you to go through

Use cases in Wikipedia

Agile Use Cases in Four Steps by Matt Terski

In my humble opinion, try to write very lightweight use cases instead of the very descriptive essay.

Creating reliable “Objects”

Let’s start of with a piece of code.

We have a Main( ) method, which creates an object of a Circle class, sets the radius and then calculates the area of the circle. Let’s have a look at the circle class. It has a simple implementation to calculate the area of circle.

The above code looks simple and it works. Are there any flaws in it? Let’s examine.

What if the consumer of the Circle class, does not set the radius correctly? For example, like this,

circle.Radius = Convert.ToInt32("abc");

The call to CalculateArea( ) would fail, because the input cannot be parsed into an integer. By design, the Circle class  is allowing other classes to control the Radius property. The consuming classes, may set unacceptable values for the Radius property. This leads to unpredictable results from the CalculateArea( ) method. We can do a validation check for the Radius property either in it’s setter or the CalculateArea( ) method. That would work. Perhaps that is a natural approach we adopt most of the time.

But let us for a moment take a step back and think more in terms of object orientation. Imagine someone asks you to draw a circle on a piece of paper. Your obvious question would be, “Sure, how big or small do you want it?”. In other words, in order to “construct” a circle, you would need the information about it’s radius.

One more important aspect in this example, is that a Circle is immutable. Once we create circle with a certain radius, we cannot change it. Making the setter for Radius property as public allows the consuming classes to alter it, even after it has been created (Hmm, not good.)

It is therefore always a good idea to create objects in a robust way, when they are being constructed. The radius property is integral to the Circle class and it is the responsibility of Circle class to manage it. The clients just need to provide the details while creating the objects. If the client code provides incorrect information while constructing the object, the class can choose not to go further with its creation, thereby protecting its integrity.

Below would be the correct implementation of Circle class.
The above example was a simple one. We just had one property to deal with. But in reality, we need to deal with classes which have a lot of properties and really complex methods. Ensuring correct values in all properties throughout the lifetime of an object can be a very tedious task. This leads to many potential bugs. It is impossible to predict the ways in which the consumers of the classes would consume them. This leads to responsibilities scattered all over the place and classes that are strongly dependent on each other.

In addition, once we make a property as public, it is very difficult to make it private again, because by the time you realize that you need to do that, there may be a number of places, it has already been consumed and used in different ways.

As a thumb rule, try to restrict the access to all the properties in the class when you write it for the first time. This will allows you to encapsulate the class properties and the code to manage them inside the class itself. If you need to make any property as protected, internal or public, think and try to find for a strong need and justification for doing so.

 

Fail as early as possible

The inspiration behind this blog post is, of course, the Clean code book.

Sometimes, people choose to use unnecessary deep conditionals.

They choose to return error/exception from else part of the deeply nested conditionals. It hampers the readability.

We will consider the use case of register user which requires three mandatory fields: Name, Email, and Password. (Let’s keep it simple.)

Let me walk you through a code that was created to showcase the problem of deep nesting. This was a part of the method “RegisterUser” that accept user object.

RegisterUser(User user) routine and User has Name, Email and Password fields.

This code snippet creates a little-complicated decision matrix in your head, especially for the Else part.

When User’s Name is NOT empty && User’s email is NOT empty && User’s password is NOT empty then store user and also send a notification for that user.

Whereas Else part was more complicated and may read like:

  • When User’s name is empty then throw an exception for the name is required.
  • When User’s name is NOT empty but user’s email is empty then throw an exception for the email is required.
  • When User’s name is NOT empty and the user’s email is NOT empty but the user’s password is empty then throw an exception for the password is required.

To make it simple, use guard clause to fail early or fail fast. All if clause in below snippet is guard clause.

Now, this one reads like

  • Throw exception for the name as soon as the user’s name is empty.
  • Throw exception for the email as soon as the user’s email is empty.
  • Throw exception for the password as soon as the user’s password is empty.
  • Otherwise, store user and send a notification to the user.

Thus, the fail-fast/fail early would make the code simpler.

Guard clause in such scenarios helps us to improve understandability.

The end result:

Repeating yourself? Wait! You could avoid the repetition.

In software development, there is this term Don’t repeat yourself. There are many posts which talk about it and terms like DRY, DRYness, WET, “write everything twice”, “we enjoy typing” or “waste everyone’s time”, and so on.

When you are repeating yourself, it’s a clue, an opportunity for you to do something about this repetition.

I’ll walk you through some of the examples.

As a developer, the first thing I was doing every morning was open the visual studio, get the latest code from TFS, build the dependencies (dependent projects), copy dll’s to the shared folder and build the main web project. I was doing this action daily in the morning. I saw I could have automated the process.

It was a clue! I created a bat file. The bat file was doing the above repetitive actions for me as soon as I start my computer.

In your case, it could be something else. It could get latest code from git, docker up, build containers and so on. Are you repeating yourself?

Whenever you see you are copying and pasting the bunch of HTML and CSS code to display a notification message. Just stop there! think about reusable HTML components, extract it and use it everywhere. Write once and use everywhere.

Whenever you see you are repeating the code to download CSV on multiple pages, then think about extracting it to a class, CsvContentGenerator? CsvDownloader?

Whenever you see you are repeating inline calculation?

 
if((totalStudentInClass - studentPresentInClass)>0){
    var message = "There are {totalStudentInClass - studentPresentInClass} absent students in the class";
}

Consider extracting it to a method or a variable.


var absentStudentsCount = totalStudentInClass - studentPresentInClass; 
if(absentStudentsCount>0){
   var message = "There are {absentStudentsCount} absent students in the class";
}

Whenever you see you are copying an email sending code from one project to another, consider writing a shared library.

Whenever you see you are repeatedly writing the validation messages in translation files. Consider writing the generic message in translation file and fill specific field name at runtime.

Check the support for it in your translation framework.


"EmailIsRequired": "Email is required".
"UsernameIsRequired": "Username is required".
"NameIsRequired": "Name is required".

// Instead of repeating, create generic message and 
// fill template-placeholder %{fieldName} with actual field name.
"FieldIsRequired": "%{fieldName} is required"

Whenever you see you are creating padding and margin styles and your app.css is growing.
Consider writing SCSS helpers, https://gist.github.com/jacurtis/30da4bf9a6c9b9b5cc0aebac512ca7c9.

Whenever you see you are writing repetitive if/switch case to decide and create a specific instance of a class. Consider using abstract factory pattern which decides and create the specific instance of a class for you.

We don’t know everything. It’s okay.

Whenever you see you are repeating something, I want you to stop there, think about it, there will be a clean solution. This could save your future time and code could be more maintainable.

In the software development field, patterns, practices, refactoring techniques and many more other techniques are already there to avoid repetition, use it.

You must be using the combination of key Ctrl+C, Ctrl+V million times a day. Next time when you press this combination, I want you to think about avoiding the repetition and ask yourself. Oh! wait! Can I do something about it? Can I automate this? Can I extract this logic to the method, classes, reusable CSS, js components, library and so on?

Why giving meaningful names to things in programming is important

Everything in this world has meaningful names. It helps our brain to understand and remember the things very easily. It means less mental mapping.

Let us take real-world examples of meaningful names given to things like hand wash (of course, you don’t use it to wash your face), face wash, shaving cream, aftershave and so on.

Similarly, in the programming, everything needs to have a meaningful name because we as a developer spend our most of the time reading the code than we do writing it.

As a developer, our daily job is to give a solution to the problem at hand.

To solve the problem at hand, we sometimes create a project, an assembly, a namespace,  directories, class files, classes, fields, methods, other members, UI elements, their translation files, translation keys and so on.

All of these things should have the meaningful name so that they convey their intent and you realize what they are doing by just looking at their name.

Perhaps they answer all the big questions that you or future maintenance developers would have.

Let’s go through the following code snippet. It is written in js.

  downld(recs){ 
        const cols = ['Name', 'Age', 'Gender'];
        let d = `data:text/csv;charset=utf-8,${cols.join(',')}rn`;
        recs.each((r) => {
            const row = [
                r.get('name'),
                r.get('age'),
                r.get('gender')
            ].join(",");

            d += `${row}rn`;
        });
        const u = encodeURI(d);
        const lnk = document.createElement("a");
        lnk.setAttribute("href", u);
        lnk.setAttribute("download", "users.csv");
        document.body.appendChild(lnk);
        lnk.click();
  }

I hope you understood what it is doing.

The above example shows that a simple code snippet could be difficult to understand when meaningful names are NOT given to variables, functions and so on.

Now think about a project that has 100+ classes and thousands of lines.

Don’t you think it will be painful for the maintenance developer as well as an original developer to read it again in the future?

This could have been easy to understand when good names would have been given.

Let us try to give the meaningful name in the code snippet.

  downloadAsCsv(users){ 
        const columnNames = ['Name', 'Age', 'Gender'];
        const csvHeader = `data:text/csv;charset=utf-8,${columnNames.join(',')}rn`;
        let csvDataRows = "";
        const newlineAndCarriageReturn = `rn`;
        users.each((user) => {
            const currentRow = [
                user.get('name'),
                user.get('age'),
                user.get('gender')
            ].join(",");

            csvDataRows += currentRow + newlineAndCarriageReturn;
        });

        const csvFileContent = csvHeader + csvDataRows;
        const encodedUri = encodeURI(csvFileContent);
        const newlink = document.createElement("a");
        newlink.setAttribute("href", encodedUri);
        newlink.setAttribute("download", "users.csv");
        document.body.appendChild(newlink);
        newlink.click();
  }

Now, do you think it’s a little better than the previous version?

The good names encourage you to write clean and good code. You can go one step ahead and split above function.

    downloadAsCsv(users){
        const csvFileContent = this.generateCsvContent(users);
        const encodedUri = encodeURI(csvFileContent);
        const newlink = document.createElement("a");
        newlink.setAttribute("href", encodedUri);
        newlink.setAttribute("download", "users.csv");
        document.body.appendChild(newlink);
        newlink.click();
    }

    generateCsvContent(users) {
        const columnNames = ['Name', 'Age', 'Gender'];
        const csvHeader = `data:text/csv;charset=utf-8,${columnNames.join(',')}rn`;
        let csvDataRows = "";
        const newlineAndCarriageReturn = `rn`;
        users.each((user) => {
            const currentRow = [
                user.get('name'),
                user.get('age'),
                user.get('gender')
            ].join(",");

            csvDataRows += currentRow + newlineAndCarriageReturn;
        });

        return csvHeader + csvDataRows;
    }

I hope you agree with me that meaningful names will make everyone (including you) more than happy after reading it.

In case of methods, when you failed to give a name to a method, you may realize it’s doing more than one thing. It is really helping you.

Even when you are able to give a meaningful name to a method, you may realize that the method doesn’t belong to this class.

I often realized that this practice of giving meaningful names helped me a lot about understanding the solutions, separations of concerns and even responsibility of the classes, methods, assembiles and so on.

Suppose your boss comes to you and asks you to fix value against gender column in generated CSV (from above example) on priority. Instead of debugging and finding the location of the code, just ask IDE to show you “generateCsvContent” routine.

Thus, help your IDE to help you by giving meaningful names to everything in programming so that you can figure out everything very easily.

Consequently, giving meaningful names will help you in some way or other.

When you revisit your code after 4 hours or 4 weeks, or 4 years, and you think you could give more meaningful names now then

DO NOT hesitate to rename it if it’s not breaking anything and has less impact on other features.

REMEMBER!

https://blog.beingcraftsman.com/datta/