Beyond the Tutorials: A Realistic Look at Coding in the Real World – Part 1
Tags: programming, tutorial, dotnetcore
Published: 2023-01-28 12:06:20

<!-- wp:paragraph -->
<p>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.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Project Requirement</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>I need to design a survey system. It will have 3 main screen.</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><!-- wp:list-item -->
<li>Admin will create an user. User email will be unique. User will also have name, mobile, isActive field.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>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.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>User can participate in the survey with a link from email.</li>
<!-- /wp:list-item --></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>The flow would be like this - User create page with user list in the bottom (with number of surveys participated) -&gt; survey creation page -&gt; survey list page with option to send invitation to all ACTIVE users -&gt; 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. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Requirement and validations:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><!-- wp:list-item -->
<li> Using Dot-net core (not webform or anything)</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Using some sort of front end technology (angular/react)</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Using entity framework</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Each survey questions will have only one answer</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Proper front end validation</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>In user page; show count of surveys that an user participated</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Implement some sort of email gateway to send mails</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>My Initial Thinking Process</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>I have assumed few things that have proved costly (or wrong) down the road. For example:<br>I should have picked code first or database first approach. <br>I picked neither. <br>And I thought I would just create the table with SQL and bind them with rest Api project. <br>BIG MISTAKE.<br>Why?<br>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. <br>But that didn't work very well.<br><br>I didn't think about making surveys dynamic with number of questions; and for that reason my submission table is stuck with 3 answers.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Designing Database</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>My initial db design has 6 tables - user, survey, question, answer, invitation, submission.<br>And my create table script is like below:</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>CREATE TABLE &#91;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 &#91;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 &#91;user](id)
);</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Can you spot any issues with this query? (Hint: not setting any identity was a huge pain in the - "ahem" - heart)</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Creating Backend Project</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Alongside this; I also created the backend project. From visual studio; go to create new project -&gt; ASP.NET core web api -&gt; 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:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":847,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://asifulhaque.com/wp-content/uploads/2023/01/Folder-Structure.png" alt="" class="wp-image-847"/><figcaption class="wp-element-caption">Folder Structure</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>I then proceeded to add the required DTOs (and entities also; as I thought re-using them would be so easy!)</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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; }</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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; }
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>namespace dev_test.DTOs
{
    public class Question
    {
        public int Id { get; set; }
        public int SurveyId { get; set; }
        public string Text { get; set; }
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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; }
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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; }
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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; }
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>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!)</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":933,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://asifulhaque.com/wp-content/uploads/2023/01/is-programming-hard-a-guide-to-getting-started-in-2022-scaled-1-1024x819.jpeg" alt="Tutorials_2" class="wp-image-933"/></figure>
<!-- /wp:image -->

<!-- wp:heading {"level":3} -->
<h3>Adding Controllers</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>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:</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>namespace dev_test.DTOs
{
    public class QuestionComposite // dto
    {
        public int SurveyId { get; set; }
        public string Text { get; set; }
        public List&lt;Answer&gt; Answers { get; set; }
    }
}</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>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&lt;Question&gt; Questions { get; set; }
    }
}</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>using dev_test.DTOs;

namespace dev_test.Repositories.Contracts // repository interface
{
    public interface IUserRepository
    {
        public IEnumerable&lt;User&gt; GetUsers();
        public void PostUser(User user);
    }
}</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>using dev_test.DTOs;

namespace dev_test.Repositories.Contracts // repository interface
{
    public interface ISurveyRepository
    {
        public IEnumerable&lt;SurveyComposite&gt; GetSurveys();
        public void PostSurveys(SurveyComposite survey);
    }
}</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>
using dev_test.DTOs;

namespace dev_test.Services.Contracts //  service interface
{
    public interface IUserService
    {
        public IEnumerable&lt;User&gt; GetUsers();
        public void PostUser(User user);
    }
}
</code></pre>
<!-- /wp:code -->

<!-- wp:code -->
<pre class="wp-block-code"><code>using dev_test.DTOs;

namespace dev_test.Services.Contracts //  service interface
{
    public interface ISurveyService
    {
        public IEnumerable&lt;SurveyComposite&gt; GetSurveys();
        public void PostSurveys(SurveyComposite survey);
    }
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>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. <br>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 ...)</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Other episodes in this series:</strong><br><a href="https://asifulhaque.com/when-programming-tutorials-doesnt-work-part-1/">First Part</a><br><a href="https://asifulhaque.com/beyond-the-tutorials-a-realistic-look-at-coding-in-the-real-world-part-2/">Second Part</a><br><a href="https://asifulhaque.com/beyond-the-tutorials-a-realistic-look-at-coding-in-the-real-world-part-3/">Third Part</a><br><a href="https://asifulhaque.com/beyond-the-tutorials-a-realistic-look-at-coding-in-the-real-world-part-4/">Fourth Part</a><br>And the code is given is updated into - <br><a href="https://github.com/asifbuetcse/dev-test" target="_blank" rel="noreferrer noopener">Github</a></p>
<!-- /wp:paragraph -->