DEV Community

Cover image for Beyond the Tutorials: A Realistic Look at Coding in the Real World – Part 1
asifbuetcse
asifbuetcse

Posted on

Beyond the Tutorials: A Realistic Look at Coding in the Real World – Part 1

Programming tutorials shows us a land of promise where everything happens as you think; as soon as you think. But real world doesn't work that way most of the times. Here; you spend hours debugging some CORS error or thinking why your database table Id column is not auto-incrementing. For the last 2 days; I am participating in a coding interview which spans 2 days and these series of blog is based on that experience - what am I thinking at each stage; what is the issue and how I am resolving them.

Project Requirement

I need to design a survey system. It will have 3 main screen.

  1. Admin will create an user. User email will be unique. User will also have name, mobile, isActive field.
  2. Admin will create a survey. For simplicity, a survey will have only 3 questions. Each questions will have 4 answers. only one answer can be selected as correct answer. Each question will have one and only one correct answer.
  3. User can participate in the survey with a link from email.

The flow would be like this - User create page with user list in the bottom (with number of surveys participated) -> survey creation page -> survey list page with option to send invitation to all ACTIVE users -> user participating in survey. After creating a survey; in the survey list there will be option to send emails to each user with unique link (unique to each user for each survey) to take the survey.

Requirement and validations:

  • Using Dot-net core (not webform or anything)
  • Using some sort of front end technology (angular/react)
  • Using entity framework
  • Each survey questions will have only one answer
  • Proper front end validation
  • In user page; show count of surveys that an user participated
  • Implement some sort of email gateway to send mails

My Initial Thinking Process

I have assumed few things that have proved costly (or wrong) down the road. For example:
I should have picked code first or database first approach.
I picked neither.
And I thought I would just create the table with SQL and bind them with rest Api project.
BIG MISTAKE.
Why?
Because then comes my second mistake. As I am not using migrations; I assumed I could just pass Entities object as DTO objects and cuts out the auto mapping portion.
But that didn't work very well.

I didn't think about making surveys dynamic with number of questions; and for that reason my submission table is stuck with 3 answers.

Designing Database

My initial db design has 6 tables - user, survey, question, answer, invitation, submission.
And my create table script is like below:

CREATE TABLE [user]
(
    id INT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    mobile VARCHAR(15) NOT NULL,
    isActive BIT NOT NULL,
    role VARCHAR(255) NOT NULL
);

CREATE TABLE survey
(
    id INT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    created_date DATETIME NOT NULL,
    updated_date DATETIME NOT NULL
);

CREATE TABLE question
(
    id INT PRIMARY KEY,
    survey_id INT NOT NULL,
    text NVARCHAR(MAX) NOT NULL,
    FOREIGN KEY (survey_id) REFERENCES survey(id)
);

CREATE TABLE answer
(
    id INT PRIMARY KEY,
    question_id INT NOT NULL,
    text NVARCHAR(MAX) NOT NULL,
    is_correct BIT NOT NULL,
    FOREIGN KEY (question_id) REFERENCES question(id)
);


CREATE TABLE invitation
(
    id INT PRIMARY KEY,
    survey_id INT NOT NULL,
    user_id INT NOT NULL,
    invitation_link NVARCHAR(MAX) NOT NULL,
    FOREIGN KEY (survey_id) REFERENCES survey(id),
    FOREIGN KEY (user_id) REFERENCES [user](id)
);


CREATE TABLE submission
(
    id INT PRIMARY KEY,
    survey_id INT NOT NULL,
    user_id INT NOT NULL,
    answer1 INT NOT NULL,
    answer2 INT NOT NULL,
    answer3 INT NOT NULL,
    score INT NOT NULL,
    FOREIGN KEY (survey_id) REFERENCES survey(id),
    FOREIGN KEY (user_id) REFERENCES [user](id)
);

Can you spot any issues with this query? (Hint: not setting any identity was a huge pain in the - "ahem" - heart)

Creating Backend Project

Alongside this; I also created the backend project. From visual studio; go to create new project -> ASP.NET core web api -> an create the app (I left authentication unchecked; another mistake; it should be fairly easy to implement and almost must do for any sort of real life project) and kept the weather forecast controller. After adding services and repositories folder; the folder structure looked like this:

Folder Structure

I then proceeded to add the required DTOs (and entities also; as I thought re-using them would be so easy!)

public int Id { get; set; }
    public int SurveyId { get; set; }
    public int UserId { get; set; }
    public int Answer1 { get; set; }
    public int Answer2 { get; set; }
    public int Answer3 { get; set; }
    public int Score { get; set; }
namespace dev_test.DTOs
{
    public class Survey
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
    }
}
namespace dev_test.DTOs
{
    public class Question
    {
        public int Id { get; set; }
        public int SurveyId { get; set; }
        public string Text { get; set; }
    }
}
namespace dev_test.DTOs
{
    public class Answer
    {
        public int Id { get; set; }
        public int QuestionId { get; set; }
        public string Text { get; set; }
        public bool IsCorrect { get; set; }
    }
}
namespace dev_test.DTOs
{
    public class Invitation
    {
        public int Id { get; set; }
        public int SurveyId { get; set; }
        public int UserId { get; set; }
        public string InvitationLink { get; set; }
    }
}
namespace dev_test.DTOs
{
    public class Submission
    {
        public int Id { get; set; }
        public int SurveyId { get; set; }
        public int UserId { get; set; }
        public int Answer1 { get; set; }
        public int Answer2 { get; set; }
        public int Answer3 { get; set; }
        public int Score { get; set; }
    }
}

The thinking process behind Submission class is that as there would only be 3 questions (from requirement); I should just save all the submission data in one class (another mistake; it stopped the system to made any change so much difficult!)

Tutorials_2

Adding Controllers

Then I added 2 controllers - UserController and SurveyController with read/write methods (deleted edit and delete methods as they were out of scope). But designing SurveyController posed an issue. As survey is not only survey table; but it has some questions and answers; it was interesting how to receive data from the front-end. I thought about creating a composite object to receive as I decided to use reactive form in the front end with angular. I also added 2 repository with their interface and 2 services with their interfaces for user and survey. These classes are as follows:

namespace dev_test.DTOs
{
    public class QuestionComposite // dto
    {
        public int SurveyId { get; set; }
        public string Text { get; set; }
        public List<Answer> Answers { get; set; }
    }
}
namespace dev_test.DTOs
{
    public class SurveyComposite // dto
    {
        public string Title { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
        public List<Question> Questions { get; set; }
    }
}
using dev_test.DTOs;

namespace dev_test.Repositories.Contracts // repository interface
{
    public interface IUserRepository
    {
        public IEnumerable<User> GetUsers();
        public void PostUser(User user);
    }
}
using dev_test.DTOs;

namespace dev_test.Repositories.Contracts // repository interface
{
    public interface ISurveyRepository
    {
        public IEnumerable<SurveyComposite> GetSurveys();
        public void PostSurveys(SurveyComposite survey);
    }
}

using dev_test.DTOs;

namespace dev_test.Services.Contracts //  service interface
{
    public interface IUserService
    {
        public IEnumerable<User> GetUsers();
        public void PostUser(User user);
    }
}
using dev_test.DTOs;

namespace dev_test.Services.Contracts //  service interface
{
    public interface ISurveyService
    {
        public IEnumerable<SurveyComposite> GetSurveys();
        public void PostSurveys(SurveyComposite survey);
    }
}

If you are using Visual Studio 2022; you might be seeing some warning here and there. Pay close attention to those. They are trying to tell something.
I then thought about writing the solid classes for the repo and service contracts; but then I remembered I don't have any way to connect to db or dbcontext or something like that. So I decided to add that to the project. (Will be continued ...)

Other episodes in this series:
First Part
Second Part
Third Part
Fourth Part
And the code is given is updated into -
Github

Top comments (2)

Collapse
 
sarahokolo profile image
sahra 💫

An Awesome read indeed👍. I realized that this article is a part in a series, you might want to check out this guide on how create a series on DEV, as it would help curate the articles in the series in a more organized and chronological order for your readers.

Collapse
 
asifbuetcse profile image
asifbuetcse

Thank you very much. I would definitely check it out and modify my series accordingly.