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.
- Admin will create an user. User email will be unique. User will also have name, mobile, isActive field.
- 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.
- 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:
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!)
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 …)
Why Tutorials Alone Won’t Make You a Great Developer: Understanding Real-World Coding
The reliance on coding tutorials as a primary learning resource has become wide- spread among aspiring developers, yet many find that such tutorials alone are insuf- ficient for mastering the complexities of real-world programming. This phenomenon, often referred to as “tutorial hell,” highlights the limitations of tutorials, which can lead to superficial understanding and lack of practical application of coding skills.[1][2] Tutorials typically fail to provide the interactive engagement necessary for deep learning, oversimplify complex concepts, and present idealized scenarios that do not accurately reflect real-life coding challenges.[3][4] As a result, learners often struggle to bridge the gap between theoretical knowledge and practical expertise.
One of the most significant drawbacks of tutorials is their passive consumption nature, which can inhibit cognitive processing essential for retaining information and problem-solving.[1] Additionally, tutorials typically adopt a one-size-fits-all approach, neglecting the diverse learning needs and paces of individuals.[1][3] This can lead to frustration and confusion, especially for beginners who may find it difficult to navigate
their learning path without adequate guidance.[5] Without practical experience and hands-on projects, learners may also miss out on developing critical skills and confidence required to tackle real-world programming tasks effectively.
To overcome these limitations, it is crucial for aspiring developers to adopt a mul- tifaceted approach that complements tutorials with practical experiences such as internships, collaborative projects, and coding challenges.[6] Engaging in these activities not only fosters a deeper understanding of programming concepts but also equips learners with the problem-solving abilities and teamwork skills that are highly valued in the tech industry. Continuous learning and adaptation to new technologies further enhance a developer’s capability to thrive in a rapidly evolving job market, ensuring they remain competitive and effective in their careers.[7][8] Thus, while tutorials can serve as an entry point into the world of coding, they should be part of a broader, more interactive learning strategy that emphasizes real-world application and collaboration.
The Limitations of Tutorials
While coding tutorials are a popular resource for learning programming, they come with several inherent limitations that can hinder true understanding and skill develop- ment. These limitations can prevent learners from achieving the depth of knowledge and practical experience necessary for success in real-world programming.
Lack of Interactivity
Most tutorials function as one-way communications, providing little opportunity for learners to engage in a dialogue with the instructor or seek real-time feedback on their understanding[1]. This absence of interaction can leave learners with unaddressed questions and misconceptions.
Oversimplification of Concepts
Tutorials often present idealized scenarios that do not accurately reflect the messy realities of coding[1][3]. By simplifying complex concepts or skipping over common errors for brevity, tutorials can give a distorted view of programming, which may lead to confusion when learners face more complex, real-world problems.
Passive Consumption of Material
Watching tutorials tends to be a passive activity where learners do not actively engage with the material[1]. This lack of active participation can diminish the cognitive processing that is crucial for understanding and retaining information, leading to what some call “tutorial hell,” where learners find themselves stuck in an endless cycle of consumption without practical application[4].
One-Size-Fits-All Approach
Tutorials often follow a fixed format that does not adapt to individual learning styles or paces[1]. This rigidity can be detrimental to learners who may require different approaches or who have varying levels of prior knowledge. As a result, learners might find themselves struggling to keep up or disengaging altogether.
Lack of Practical Application
One significant drawback of relying solely on tutorials is the limited opportunity for practical application of learned concepts[3]. Engaging in hands-on projects is
vital for developing real-world skills and gaining the confidence to tackle challenges independently. Tutorials do not typically provide the same level of engagement that project work does, leading to potential gaps in practical knowledge.
Challenges in Finding the Right Learning Path
For beginners, determining the correct path to follow can be daunting. Without a clear direction, learners may end up wasting time on tutorials that do not align with their long-term goals or learning needs[5]. This uncertainty can lead to frustration and impede progress.
The Need for Supplementary Learning Strategies
To counteract these limitations, it is essential for learners to adopt a multifaceted approach to education. This can include seeking mentorship, engaging in hands-on projects, and leveraging interactive learning platforms to supplement tutorials[6].
By actively applying concepts in real-world scenarios, learners can bridge the gap between passive learning and true mastery of programming skills[1].
The Role of Practical Experience
Practical experience is a crucial element in developing strong coding skills and understanding real-world applications of programming concepts. While theoretical knowledge from tutorials is valuable, it is through hands-on experience that individ- uals can truly excel in the field of software development.
Importance of Hands-On Training
Engaging in hands-on training allows learners to apply the concepts they’ve studied in a real-world context, bridging the gap between theory and practice. This experiential learning enhances problem-solving abilities, as students are faced with real coding challenges that require methodical thinking and the ability to break down complex problems into manageable components[7][9]. Moreover, hands-on training fosters familiarity with industry standards and tools, which is essential for anyone entering the programming workforce[9].
Types of Practical Experience
Internships and Apprenticeships
Internships and apprenticeships provide invaluable opportunities for aspiring devel- opers to work alongside experienced professionals. These programs enable partici- pants to gain practical experience while receiving mentorship, which enhances their understanding of the industry and prepares them for future job roles[7]. By working on actual projects, individuals can apply classroom knowledge and develop a versatile skill set that is attractive to potential employers.
Real-World Coding Challenges
Participating in real-world coding challenges allows learners to confront practical problems that reflect those encountered in professional environments. These chal- lenges not only improve engagement and motivation but also help in building a portfolio that showcases completed projects to potential employers[9][10]. Such experiences reinforce critical thinking and foster collaboration skills, as many coding challenges are tackled in teams, simulating a real-world work atmosphere[9].
Continuous Learning and Adaptation
In the rapidly evolving tech industry, continuous learning and adaptation are crit- ical for success. As new technologies, programming languages, and frameworks emerge, developers must remain proactive in updating their skill sets to meet the ever-changing demands of the job market. Embracing a lifelong learning mindset not only enhances one’s adaptability but also helps in securing long-term career growth and relevance in the field[7][8].
Importance of Continuous Learning
Continuous learning is no longer just a choice; it has become a necessity for professionals aiming to thrive in their careers. The fast-paced nature of technological advancements means that skills can quickly become obsolete. By actively engaging in learning opportunities—such as online courses, workshops, and industry certifi- cations—developers can bridge the gap between their existing skills and the com- petencies required for future roles[7][11]. This commitment not only fosters personal satisfaction but also contributes to overall well-being, as the pursuit of knowledge can stimulate intellectual curiosity and open doors to new opportunities[11][8].
Strategies for Effective Skill Development
To effectively navigate the complexities of skill development, developers should adopt several strategies:
Identify Skill Gaps: Regularly assess personal skills and identify areas needing improvement. This self-reflection can guide the selection of relevant learning re- sources[11].
Leverage Various Learning Methods: Embrace a mix of formal education, self-study, and on-the-job experience. This diversified approach can include attending training
workshops, participating in online coding boot camps, or engaging in mentorship programs[11].
Build Projects: Practical application of skills through personal or collaborative projects can solidify knowledge and enhance problem-solving abilities. Starting with small projects and gradually increasing complexity allows for continuous skill advance- ment[12][13].
Join Developer Communities: Engaging with fellow developers through forums and online communities can provide invaluable feedback and support. Such interactions help overcome challenges and motivate continuous improvement[12].
Manage Time Effectively: Balancing learning with other responsibilities is crucial. Es- tablishing a dedicated routine for skill development can facilitate consistent progress in one’s educational journey[12][13].
Overcoming Challenges
Despite the myriad benefits of continuous learning, individuals often face hurdles such as time constraints and the fear of failure. Overcoming these challenges requires a proactive approach. Setting realistic goals, seeking support from peers, and main- taining a growth mindset can empower developers to navigate their skill development journey more effectively[11][14]. Embracing change and viewing setbacks as learning opportunities can lead to greater resilience and adaptability in the face of industry shifts[7][8].
The Value of Collaboration
Collaboration is essential in the realm of software development, as it significantly enhances the effectiveness and quality of coding projects. In an environment where developers often work in teams, understanding and implementing collaborative prac- tices can lead to more innovative solutions and higher productivity.
Understanding the Importance of Collaboration
Effective collaboration goes beyond merely sharing code; it encompasses communi- cation, teamwork, and problem-solving. When developers collaborate efficiently, they can share ideas and insights, resulting in faster problem resolution and improved code quality. Strategies for fostering collaboration include establishing clear com- munication channels, using version control systems, and conducting regular code reviews[15][16].
Establishing Clear Communication Channels
Clear communication is fundamental for successful collaboration. Utilizing messag- ing platforms like Slack or Microsoft Teams facilitates real-time discussions, while regular meetings can keep team members aligned on project progress and objec- tives. Comprehensive documentation of coding standards and project goals is also
crucial to ensure all members have access to the same information, thus minimizing misunderstandings[15][17].
Version Control Systems
Implementing a version control system, such as Git, is vital for managing collaborative coding efforts. A VCS allows multiple developers to work on the same codebase simultaneously, reducing conflicts and preserving a history of changes. This is par- ticularly important during large-scale merges, which require careful coordination and communication to ensure smooth integration of code[18][11].
Promoting Cross-Functional Collaboration
Encouraging collaboration between different functional teams—such as developers, testers, and operations—can yield more comprehensive solutions. This cross-func- tional approach fosters a culture of shared responsibility and enhances the overall quality of the code produced. By involving diverse perspectives, teams can address potential issues more effectively and creatively[18][19].
Fostering a Positive Team Environment
A supportive team culture is integral to successful collaboration. By promoting exper- imentation and encouraging team members to share their insights, organizations can create an atmosphere where innovation flourishes. This includes recognizing the im- portance of soft skills and emotional intelligence, which facilitate better interpersonal relationships and communication among team members[17][19].
Real-World Examples of Successful Collaboration
Several prominent organizations have exemplified the benefits of collaborative prac- tices. For instance, GitHub utilizes a collaborative platform that emphasizes version control and documentation, enabling teams from various locations to work togeth- er seamlessly. Similarly, Google implements Agile methodologies and continuous integration processes to enhance collaboration among its vast teams, allowing for the rapid delivery of high-quality products. Spotify’s innovative structure of Squads, Tribes, and Chapters further illustrates the advantages of a collaborative approach in promoting teamwork[17][18].
Building a Portfolio
Creating a strong portfolio is essential for aspiring developers seeking to enter the job market. A well-curated portfolio showcases skills and completed projects, serving as a practical demonstration of a developer’s abilities and potential to employers.
Importance of a Portfolio
A robust portfolio not only reflects a candidate’s technical skills but also illustrates their adaptability and practical application of programming knowledge. Through
real-world projects, developers can highlight their experience in solving industry-spe- cific problems, thus enhancing their appeal to potential employers[20][21].
Strategies for Building a Portfolio
Project Selection
When curating a portfolio, it is crucial to select a few clean and well-documented projects that effectively highlight coding abilities. Aim to include 3-5 projects that showcase a range of skills, avoiding unfinished or low-quality work[12]. Clear README files explaining the project’s purpose, technologies used, key learnings, and challenges faced can significantly enhance the portfolio’s professionalism[12].
Types of Projects
Engaging in various types of projects helps build a diverse portfolio. Personal projects, contributions to open-source initiatives, and completed coding challenges are all valuable additions[22].
Personal CV Website: A portfolio website to showcase skills and projects.
Contact Manager: A single-page application (SPA) that demonstrates client-side development using libraries like React or Angular.
Sports Timer: An application that tracks time, providing experience in user interface design and JavaScript[23].
Continuous Improvement
A mindset of continuous learning is crucial in software development. Developers should remain informed about industry trends and emerging technologies, allowing them to adapt their portfolios accordingly. Regularly updating the portfolio with new projects and skills ensures that it remains relevant and competitive in the fast-paced tech landscape[21].
Engaging with the Tech Community
Networking plays a pivotal role in building a portfolio. By participating in local
meet-ups, online forums, and hackathons, developers can gain insights from expe- rienced professionals and discover job openings. Platforms such as LinkedIn and GitHub are invaluable for connecting with peers and potential employers, further enhancing one’s professional presence[21].
Continuous Learning and Adaptation
In the rapidly evolving tech industry, continuous learning and adaptation are crit- ical for success. As new technologies, programming languages, and frameworks
emerge, developers must remain proactive in updating their skill sets to meet the ever-changing demands of the job market. Embracing a lifelong learning mindset not only enhances one’s adaptability but also helps in securing long-term career growth and relevance in the field[7][8].
Importance of Continuous Learning
Continuous learning is no longer just a choice; it has become a necessity for professionals aiming to thrive in their careers. The fast-paced nature of technological advancements means that skills can quickly become obsolete. By actively engaging in learning opportunities—such as online courses, workshops, and industry certifi- cations—developers can bridge the gap between their existing skills and the com- petencies required for future roles[7][11]. This commitment not only fosters personal satisfaction but also contributes to overall well-being, as the pursuit of knowledge can stimulate intellectual curiosity and open doors to new opportunities[11][8].
Strategies for Effective Skill Development
To effectively navigate the complexities of skill development, developers should adopt several strategies:
Identify Skill Gaps: Regularly assess personal skills and identify areas needing improvement. This self-reflection can guide the selection of relevant learning re- sources[11].
Leverage Various Learning Methods: Embrace a mix of formal education, self-study, and on-the-job experience. This diversified approach can include attending training workshops, participating in online coding boot camps, or engaging in mentorship programs[11].
Build Projects: Practical application of skills through personal or collaborative projects can solidify knowledge and enhance problem-solving abilities. Starting with small projects and gradually increasing complexity allows for continuous skill advance- ment[12][13].
Join Developer Communities: Engaging with fellow developers through forums and online communities can provide invaluable feedback and support. Such interactions help overcome challenges and motivate continuous improvement[12].
Manage Time Effectively: Balancing learning with other responsibilities is crucial. Es- tablishing a dedicated routine for skill development can facilitate consistent progress in one’s educational journey[12][13].
Overcoming Challenges
Despite the myriad benefits of continuous learning, individuals often face hurdles such as time constraints and the fear of failure. Overcoming these challenges requires a proactive approach. Setting realistic goals, seeking support from peers, and main- taining a growth mindset can empower developers to navigate their skill development journey more effectively[11][14]. Embracing change and viewing setbacks as learning
opportunities can lead to greater resilience and adaptability in the face of industry shifts[7][8].
Common Challenges in Transitioning
Transitioning into programming, particularly for individuals from non-technical back- grounds, presents several unique challenges that can hinder progress and confi- dence. Understanding these obstacles is crucial for aspiring developers aiming to build a successful career.
The Cycle of Tutorial Hell
One of the most significant challenges faced by newcomers is the phenome- non known as “Tutorial Hell.” This term describes a state where individuals find
themselves endlessly consuming programming tutorials without making substantial progress in their projects or practical skills.[2] This overreliance on tutorials often leads to a lack of confidence when tackling real-world coding challenges, as learners may become trapped in a cycle of watching content instead of applying what they’ve learned. To escape this cycle, it is essential to focus on applying knowledge through hands-on projects rather than merely consuming tutorials[2][4].
Skills Gaps and Misalignment
Another challenge in transitioning is the potential for skills gaps. Many tutorials fail to cover fundamental concepts comprehensively, often addressing specific aspects of programming without providing a robust foundational understanding. As a re- sult, learners may find themselves seeking out multiple tutorials to fill these gaps, inadvertently prolonging their journey in programming.[4] To counteract this issue, it is advisable to assess one’s understanding of core concepts before diving into advanced tutorials, ensuring a well-rounded knowledge base.
Adaptability and Continuous Learning
The fast-paced nature of the tech industry requires developers to be adaptable and committed to continuous learning[7]. However, many individuals struggle with this expectation, leading to feelings of overwhelm and frustration. Developing a growth mindset—viewing challenges as opportunities for learning rather than insurmount- able obstacles—is critical for navigating this transitional phase successfully. Those who cultivate this mindset are more likely to remain engaged and proactive in their learning journey[7][2].
Collaboration and Conflict Management
As individuals begin to collaborate with others in coding projects, they may en- counter conflicts stemming from differing viewpoints or methods of problem-solving. Effectively managing these conflicts is essential not only for project success but also for personal and professional growth.[24][25] Establishing clear communication
channels and developing a structured approach to conflict resolution can enhance teamwork and foster a positive environment, further aiding the transition into a programming career.
Other episodes in this series:
First Part
Second Part
Third Part
Fourth Part
And the code is given is updated into –
Github
1 thought on “Coding Adventures: The Truth About Programming Outside Tutorials, Part 1”