9
\$\begingroup\$

I'm doing a C# tutorial by Mosh and one of the exercises is creating a program that simulates a stack overflow post upvoting/downvoting system. Very simple and short app but still wanted to know if my solution is okay and ways to improve it! I'm trying to make it as object-oriented as I possibly can, but I'm not sure I'm getting OOP correctly.

Program.cs

using System;

namespace StackOverflowPost
{
    class Program
    {
        static void Main(string[] args)
        {
            var newPost = new Post
            {
                Title = "HELLO WORLD",
                Description = "This is some awesome hello world description."
            };

            Console.WriteLine(newPost.Title);
            Console.WriteLine(newPost.Description);
            Console.WriteLine(newPost.CreationDateTime);

            newPost.UpVote();
            newPost.UpVote();
            newPost.DownVote();

            Console.WriteLine("Number of votes: " + newPost.DisplayVotes());
        }
    }
}

Post.cs

using System;

namespace StackOverflowPost
{
    class Post
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public readonly DateTime CreationDateTime = DateTime.Now;
        private int _votes;

        public int DisplayVotes()
        {
            return _votes;
        }

        public void UpVote()
        {
            _votes++;
        }

        public void DownVote()
        {
            _votes--;
        }
    }
}
\$\endgroup\$
10
\$\begingroup\$

Just keeping a count is fine for the example app, you don't want to go mad with your implementation. Consider that in real life, you need to know who voted and when. There are various rules about when you can change your vote and when it's locked in. So although your code is fine for the simple 'show me the score' question there are some that you can't answer:

  1. How many votes has the post had in the last day?
  2. What is the split of up and down votes?
  3. Am I allowed to change my vote now?
  4. Have I already voted?

All of those questions (and more) would need to be supported by your final design. If you just wanted to support 2 for now, you could track the up and down votes separately.

As for your code, I'd split out the up and down votes and add a get only property called Score.

Worth noting, if you plan on supporting multiple regions you have to store you dates and times unambiguously. Usually, that means storing in UTC.

so

DateTime.Now

Should have been

DateTime.UtcNow

If you just used the first, consider what would happen around any Daylight Saving Time transitions. When the clock goes back there is an entire hour of repeated local times. You won't be able to say which instant in UTC that the time corresponded to.

Edit

The minimal change I'd make to your code is:

public class Post
{
    public string Title { get; set; }
    public string Description { get; set; }

    // C#6 syntax for readonly property
    public DateTime CreationDateTime { get; } = DateTime.UtcNow;

    public int UpVoteCount { get; private set; }
    public int DownVoteCount { get; private set; }

    // C#6 expression bodied member
    public int Score => UpVoteCount - DownVoteCount;

    public void UpVote()
    {
        UpVoteCount++;
    }

    public void DownVote()
    {
        DownVoteCount++;
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks a lot for your answer! I will definitely keep working on the project to extend such questions once I'm done with the tutorial. And I've changed DateTime.Now to DateTime.UtcNow, tbh I didn't even know that the standard way was using Utc! Could you please clarify though what you meant by "I'd split out the up and down votes and add a get only property called Score."? Thanks! \$\endgroup\$ – user123850 Jun 10 '17 at 14:20
  • 2
    \$\begingroup\$ @Evan - I've added an update to show how I'd address issue 2. You'll find that modelling votes as a count reaches a limit of functionality you can provide pretty quickly. Dates and Times are hard because of all the incorrect assumptions we bring to it. This guy's blog (and plural sight course) are fonts of information! codeofmatt.com/2013/04/25/the-case-against-datetime-now \$\endgroup\$ – RobH Jun 10 '17 at 16:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy