Code Review: App Interfaces

https://www.codecademy.com/courses/learn-c-sharp/projects/csharp-app-interfaces

I’m unsure if I have completed the first 12 steps correctly. Was hoping someone can skim over my code and tell me if I completed all steps correctly. One thing that concerns me is what the console looks like in the screenshot versus what step 13 shows.

Todos
--------
Eat
Sleep
Code

Password
-----------
***

Program.cs

using System;

namespace SavingInterface
{
  class Program
  {
    static void Main(string[] args)
    {
      TodoList tdl = new TodoList();
      tdl.Add("Invite friends");
      tdl.Add("Buy decorations");
      tdl.Add("Party");

      PasswordManager pm = new PasswordManager("iluvpie", true);
      
      //Make sure that both classes are printable, call Display() on tdl and pm.
      //tdl.Display();
      //pm.Display();
      //Call Reset() and Display() with tdl and pm. In other words, both objects should display, then reset, then display again.
      tdl.Display();
      tdl.Reset();
      tdl.Display();

      pm.Display();
      pm.Reset();
      pm.Display();
    }
  }
}

TodoList.cs

using System;

namespace SavingInterface
{
  class TodoList : IDisplayable, IResetable
  {
    public string[] Todos
    { get; private set; }

    private int nextOpenIndex;

    public TodoList()
    {
      Todos = new string[5];
      nextOpenIndex = 0;
    }

    public void Add(string todo)
    {
      Todos[nextOpenIndex] = todo;
      nextOpenIndex++;
    }
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      foreach (string s in Todos)
      Console.WriteLine(s);
    }
    
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Todos = new string[5];
      nextOpenIndex = 0;    
    }
  }
}

PasswordManager.cs

using System;

namespace SavingInterface
{
  class PasswordManager : IDisplayable, IResetable
  {
    private string Password
    { get; set; }

    public bool Hidden
    { get; private set; }

    public PasswordManager(string password, bool hidden)
    {
      Password = password;
      Hidden = hidden;
    }
    
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      if (Hidden)
      {
        Console.WriteLine("*****");
      }
      else
      {
      Console.WriteLine(Password);
      }
    }
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Password = "";
      Hidden = false;    
    }
  }
}

IDisplayable.cs

// Define IDisplayable in this file

using System;

namespace SavingInterface
{
  interface IDisplayable
  {
    //Within IDisplayable declare one method that returns nothing
    void Display();
  }
}

IResetable.cs

// Define IResetable in this file

using System;

namespace SavingInterface
{
  interface IResetable
  {
    //define an interface with one method it should return nothing
    void Reset();
  }
}

Bumping, hoping someone will reply.

No one at all has any idea with c#?

Hi @psmilliorn! I’m a Senior Curriculum Developer and I wrote this project. Super cool to see it be a part of your learning journey!

Your code fulfills steps 1-12. In fact it looks very similar to the solution code I originally intended :grin:

Your output doesn’t look like the output in step 13 because you haven’t done the extensions. You’ll get the output shown in step 13 once you finish the first extension given (the one about HeaderSymbol and extending the Display() method).

Hope that helps! Happy to clarify anything if you have more questions.

1 Like

Thank you for responding! Yes that does clarify my concerns up to step 13. I haven’t done step 13. I know I will be needing help with it when I get back to it since I recall not grasping what it is asking. But its been a few days so maybe it will make more sense when I revisit it. Hopefully you will be OK with me pinging you again for step 13 if I get stuck.

Absolutely!

Normally we would have a project walkthrough video ready for you, but it’s in production now.

1 Like

I’m unsure how this is meant to be implemented. I get how to set it in IDisplayable.cs but not sure how the lesson wants to do the following.

Add a get-only property to IDisplayable called HeaderSymbol . This should be used in Display() as a header. For example, if the header symbol is - , then the apps should be displayed as:

Todos
--------
Eat
Sleep
Code

Password
-----------
***

Currently (if I comment out HeaderSymbol) my console looks like this.

Hey @psmilliorn sorry for the delayed response! It looks like you’re having a StackOverflowException, which may be a separate issue. Send me the Program.cs and PasswordManager.cs code and we can debug that first before getting into HeaderSymbol.

@nduckwiler

Program.cs

using System;

namespace SavingInterface
{
  class Program
  {
    static void Main(string[] args)
    {
      TodoList tdl = new TodoList();
      tdl.Add("Invite friends");
      tdl.Add("Buy decorations");
      tdl.Add("Party");

      PasswordManager pm = new PasswordManager("iluvpie", true);
      
      //Make sure that both classes are printable, call Display() on tdl and pm.
      //Call Reset() and Display() with tdl and pm. In other words, both objects should display, then reset, then display again.
      tdl.Display();
      tdl.Reset();
      tdl.Display();

      pm.Display();
      pm.Reset();
      pm.Display();
    }
  }
}

PasswordManager.cs

using System;

namespace SavingInterface
{
  class PasswordManager : IDisplayable, IResetable
  {
    private string Password
    { 
      get 
      { 
        return Password; 
      }
      set 
      {
        if (value.Length >= 8)
        {
          Password = value;
        }
      }
    }

    public bool Hidden
    { get; private set; }

    public PasswordManager(string password, bool hidden)
    {
      Password = password;
      Hidden = hidden;
    }
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      if (Hidden)
      {
        Console.WriteLine("*****");
      }
      else
      {
      Console.WriteLine(Password);
      }
    }
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Password = "";
      Hidden = false;    
    }
    //Add a method ChangePassword()
    public bool ChangePassword(string oldPass, string newPass)
    {
      return oldPass == newPass;
    }
  }
}

@psmilliorn Looks like the issue is in PasswordManager.cs. You are creating a property Password that tries to return the property Password. This creates a StackOverflowException - it’s sort of like an infinite loop but with method calls.

You’ll need to define a separate field and make the property Password set and get that field.

OK, so I believe I have cleared that up. I wanted to make sure that before we revisit…

Add a get-only property to IDisplayable called HeaderSymbol . This should be used in Display() as a header. For example, if the header symbol is - , then the apps should be displayed as:

…that the rest of step 13 is completed.

If you add more than five to-dos to the TodoList , it throws an error! Extend the Add() method so that it doesn’t add any more than five items to the Todos array.

I’m skeptical if I did this correctly based on output in console.

Currently a blank line is printed for each empty index in Todos . Change Display() in TodoList so that it prints [] instead of a blank line

Pretty sure that was done correctly.

Add a method ChangePassword() to PasswordManager .

Done.

Extend the Password property in PasswordManager

Unsure if this was correct.

Here is the following code changes.

TodoList.cs

using System;

namespace SavingInterface
{
  class TodoList : IDisplayable, IResetable
  {
    public string[] Todos { get; private set; }

    private int nextOpenIndex;

    public TodoList()
    {
      Todos = new string[5];
      nextOpenIndex = 0;
    }

    public void Add(string todo)
    {
      if (Todos.Length <= 5)
      {
        Todos[nextOpenIndex] = todo;
        nextOpenIndex++;
      }
    }
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      foreach (string s in Todos)
      {
        if (String.IsNullOrEmpty(s))
        {
          //prints [] instead of a blank line.
          Console.WriteLine("[]");
        }
        else 
        {
          Console.WriteLine(s);
        }
      }
    }
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Todos = new string[5];
      nextOpenIndex = 0;    
    }
  }
}

PasswordManager.cs

using System;

namespace SavingInterface
{
  class PasswordManager : IDisplayable, IResetable
  {
    string password;
    private string Password
    { 
      get 
      { 
        return password; 
      }
      set 
      {
        if (value.Length >= 8)
        {
          password = value;
        }
      }
    }

    public bool Hidden { get; private set; }

    public PasswordManager(string password, bool hidden)
    {
      Password = password;
      Hidden = hidden;
    }
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      if (Hidden)
      {
        Console.WriteLine("*****");
      }
      else
      {
      Console.WriteLine(Password);
      }
    }
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Password = "";
      Hidden = false;    
    }
    //Add a method ChangePassword() with two string parameters
    public bool ChangePassword(string oldPass, string newPass)
    {
      //if the first argument matches Password
      if (oldPass == Password)
      {
        //Reset Password to second argument
        Password = newPass;
      }
      //return true if password change success(first argument matched old password)
      return oldPass == newPass;
    }
  }
}

Thank you for all your help so far :smile:

@psmilliorn nice work so far! The short answer is: yes, you did both of those extensions in question. More detail below:

If you add more than five to-dos to the TodoList , it throws an error! Extend the Add() method so that it doesn’t add any more than five items to the Todos array.

You did this by adding the line:
if (Todos.Length <= 5)

Extend the Password property in PasswordManager

Technically you completed this too. Although, I would recommend setting password to a default value for if the input value is less than 8. This involves adding an else statement in your set method.

1 Like

@nduckwiler & @psmilliorn - thanks for this discussion. It’s been really helpful.

I’m still struggling with the HeaderExtension challenge. I’ve been tying myself in knots with it. Can you help at all?

Cheers!

Since these post I went back some time after and did a refactor. That part you mention was a part I also struggled with. Until the refactor I could not get it to appear how you see it in the lesson. Since then I can now get it to work.

Todos
-----------
Test
-----------
iluvpie

From Program.cs

namespace SavingInterface
{
  class Program
  {
    static void Main(string[] args)
    {
      TodoList tdl = new TodoList();
      PasswordManager pm = new PasswordManager("iluvpie", false);

      tdl.Add("Test");

      //Call Display() on tdl and pm. Run the program with:
      tdl.Display();
      pm.Display();

      //In Program.cs, call Reset() and Display() with tdl and pm. 
      //In other words, both objects should display, then reset, then display again.
      tdl.Reset();
      pm.Reset();
    }
  }
}

I can’t quite explain this well enough without showing examples so I’ll just show the relevant part I think your referencing. This is taken from PasswordManager.cs

namespace SavingInterface
{
  class PasswordManager : IDisplayable, IResetable
  {

    public string HeaderSymbol => "-----------";
  }
}

That’s not verbatim, but again an example take from there. HeaderSymbol is referenced in two places in my code.

        public void Display()
        {
            Console.WriteLine("Todos");
            Console.WriteLine(HeaderSymbol);

            foreach (String s in ToDo)
            {
                Console.WriteLine(s);
            }

            Console.WriteLine(HeaderSymbol);
        }

Display() is found in todoLists.cs I also have

 public string HeaderSymbol => "-----------";

In TodoLists.cs an I am not sure why. Its found since of

class TodoList : IDisplayable, IResetable

Anyhow, hope this help.s

Hello, I was wondering if either of you tested the Add() extension that was mentioned? Did it work when you did? I used the same “if (Todos.Length <= 5)” and then added six total Todo items and still got the same error message. I realized that the array will always be length 5 because that’s what we defined it as in the constructor. So it may have empty spots but it’s still length of 5. I resolved this issue by using this in my if statement instead: if (nextOpenIndex < 5).

Was that the intended resolution?

using System;

namespace SavingInterface
{
  class TodoList : IDisplayable, IResetable
  {
    public string[] Todos { get; private set; }

    private int nextOpenIndex;

    public TodoList()
    {
      Todos = new string[5];
      nextOpenIndex = 0;
    }

    public void Add(string todo)
    {
      if (Todos.Length <= 5)
      {
        Todos[nextOpenIndex] = todo;
        nextOpenIndex++;
      }
    }
    //Define a method that satisfies the interface requirements
    public void Display()
    {
      foreach (string s in Todos)
      {
        if (String.IsNullOrEmpty(s))
        {
          //prints [] instead of a blank line.
          Console.WriteLine("[]");
        }
        else 
        {
          Console.WriteLine(s);
        }
      }
    }
    //Define a method to satisfy the interface.
    public void Reset()
    {
      Todos = new string[5];
      nextOpenIndex = 0;    
    }
  }
}

I have since refactored this and use List but what I had that at the time worked was this.

Hello Nick,

In the extending of the Password property, I have the set like this:
set
{
if (value.Length > 7)
{ password = value;} else
{ password = “password”;}
}

This seems to have stopped the ChangePassword() method from working even if I am passing it a string of nine characters. If I write the value.Length to the console it shows as zero. Do you know what is going on there?

Hey @adamstackhouse203307,
Your set method looks okay. There might be a problem with the rest of your Password class. Could you paste in the entire Password.cs file?