首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单人事管理控制台-应用程序

简单人事管理控制台-应用程序
EN

Code Review用户
提问于 2019-02-15 19:13:38
回答 2查看 497关注 0票数 4

下面的代码是工作编码挑战的代码。我已经按照他们的要求做好了所有的事情,我已经亲自复习过了,并且相信一切都很好。我只是想看看是否有人看到我所做的事情可能被认为是不好的做法,或者是否有任何明显的改进,以清理代码或提高性能。欢迎任何反馈意见。

以下是公司给我的指示:

  1. 向用户提供一个带有3个选项查看人员,添加人员,退出的菜单
  2. 如果用户选择“查看人员”,则应用程序应显示应用程序中的人员列表。
  3. 如果用户选择'Add Person',则应该指示他们输入名称。程序应该为新的人分配一个唯一的id。
  4. 如果有人选择“退出”,应用程序应该关闭。否则,应用程序应保持运行,并/或指示选择无效。
  5. 可选:创建第四个功能,您可以根据名称进行搜索,程序指示名称是否在系统中。
  6. 使用内存中的列表存储person对象。
  7. 使用多个类和面向对象的设计来编写程序(不要将所有的逻辑都放在program类中)。
  8. 我们要找的是:
    • 程序是否符合要求/指令,是否稳定?
    • 代码是否干净&是否有适当的注释?
    • 有一个可以理解的面向对象的设计吗?

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;

namespace CSECodeSampleConsole
{


public class Program
{
    public static void Main(string[] args)
    {
        Menu menu = new Menu();
        menu.MainMenu();
    }
}

internal class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public static int globalId = 1;

    public Person(string name)
    {
        this.Name = name;
        this.Id = globalId;
        globalId++;
    }

}

internal class Menu
{
    List<Person> people = new List<Person>();
    public void MainMenu() //Display and Navigate Menu.
    {
        Console.WriteLine("Please make a selection by entering the corresponding number:");
        Console.WriteLine("1.View Persons");
        Console.WriteLine("2.Add Person");
        Console.WriteLine("3. Search For Person");
        Console.WriteLine("4.Exit");
        var input = Console.ReadLine();

        switch (Convert.ToInt32(input))
        {
            case 1:
                DisplayNames();
                break;
            case 2:
                AddPerson();
                break;
            case 3:
                SearchList();
                break;
            case 4:
                Environment.Exit(0);
                break;
            default:
                Console.WriteLine("Invalid Input\n\n");
                MainMenu();
                break;
        }
        return;
    }

    public void DisplayNames() //Display all names and their Id's in list.
    {
        if(people.Count == 0)
        {
            Console.WriteLine("No People To Display Yet.\n\n");
            MainMenu();
        }
        else
        {
            Console.WriteLine("List of Current People:\n");
            foreach (Person person in people)
            {
                Console.WriteLine(person.Id + " - " + person.Name);
            }
            Console.WriteLine("\n\n");
            MainMenu();
        }
        return;
    }

    public void AddPerson() //Add a new person to the list.
    {
        Console.WriteLine("Please Enter The Person's Name: ");
        var result = Console.ReadLine();
        Person newPerson = new Person(result);
        people.Add(newPerson);
        Console.WriteLine(newPerson.Name + " added successfully.\n\n");
        MainMenu();
        return;
    }

    public void SearchList() //Find and display search results.
    {
        Console.WriteLine("Please Enter A Name To Search For: ");
        var result = Console.ReadLine();
        var searchResults = people.Where(n => n.Name.Contains(result, StringComparison.OrdinalIgnoreCase)).ToList();

        if (searchResults.Count == 0)
        {
            Console.WriteLine("No Results Were Found");
        }
        else
        {
            Console.WriteLine("The Following Results Were Found: \n");
            foreach (Person person in searchResults)
            {
                Console.WriteLine(person.Id + " - " + person.Name);
            }
        }
        Console.WriteLine("\n\n");
        MainMenu();
    }
}

public static class MyExtensionMethods 
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {   //Created this to take away the case sensitivity of the Contains method.
        return source != null && toCheck != null && source.IndexOf(toCheck, comp) >= 0;
    }
}
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2019-02-15 19:47:11

代码的

Feedack:

代码语言:javascript
复制
this.Id = globalId;
globalId++;

可以简化为

代码语言:javascript
复制
this.Id = globalId++;

globalId不应公开

代码语言:javascript
复制
switch (Convert.ToInt32(input)) { ... }

这不是一种解析输入的健壮方法。如果用户输入一个字母,您的程序就会崩溃!

  • MainMenu()可以移动到MainMenu()方法的末尾(作为递归调用)。
  • 在方法的末尾不需要return
  • 不需要Contains-Extension方法,因为名称和搜索输入都不能为null。
  • 使用Environment.NewLineConsole.WriteLine代替"\n“。

面向对象设计

很好,有一个person类来存储关于此人的信息。

然而,因为面试官希望一个“可以理解的面向对象的设计”,我也会尝试将不同的菜单案例建模为对象。

例如:

代码语言:javascript
复制
public abstract class MenuEntry
{
    public MenuEntry(int id, string description)
    {
        this.Id = id;
        this.Description = description;
    }

    public int Id { get; }
    public string Description { get; }

    public abstract void Execut();
}

这样就可以在一个单独的类中定义每个菜单项及其逻辑,然后去掉switch语句。

此外,使用新的菜单项扩展程序更简单,而不涉及逻辑;)。

单个类条目的示例实现:

代码语言:javascript
复制
    internal class Person
    {
        public int Id { get; }
        public string Name { get; }
        private static int globalId = 1;

        public Person(string name)
        {
            this.Name = name;
            this.Id = globalId++;
        }

    }

    internal abstract class MenuEntry
    {
        public MenuEntry(int id, string description)
        {
            this.Id = id;
            this.Description = description;
        }

        public int Id { get; }
        public string Description { get; }

        public abstract void Execut();
    }

    internal class DisplayNames : MenuEntry
    {
        private readonly List<Person> persons;

        internal DisplayNames(List<Person> persons) : base(1, "View Persons")
        {
            this.persons = persons;
        }

        public override void Execut()
        {
            if (persons.Count == 0)
            {
                Console.WriteLine("No People To Display Yet.");
            }
            else
            {
                Console.WriteLine("List of Current People:");
                persons.ForEach(p => Console.WriteLine(p.Id + " - " + p.Name));
            }
        }
    }

    internal class AddPerson : MenuEntry
    {
        private readonly List<Person> persons;

        internal AddPerson(List<Person> persons) : base(2, "Add Person")
        {
            this.persons = persons;
        }

        public override void Execut()
        {
            Console.WriteLine("Please Enter The Person's Name: ");
            var result = Console.ReadLine();
            Person newPerson = new Person(result);
            persons.Add(newPerson);
            Console.WriteLine(newPerson.Name + " added successfully.");
        }
    }

    internal class Exit : MenuEntry
    {
        internal Exit() : base(9, "Exit")
        {
        }

        public override void Execut()
        {
            Environment.Exit(0);
        }
    }

    internal class Menu
    {
        private readonly List<Person> persons = new List<Person>();
        private readonly List<MenuEntry> entries = new List<MenuEntry>();

        public Menu()
        {
            this.entries.Add(new DisplayNames(this.persons));
            this.entries.Add(new AddPerson(this.persons));
            // ... other entries
            this.entries.Add(new Exit());
        }

        public void Show()
        {
            Console.WriteLine("Please make a selection by entering the corresponding number:");
            this.entries.ForEach(p => Console.WriteLine($"{p.Id}. {p.Description}"));

            var input = Console.ReadLine();

            int entryId = -1;
            MenuEntry entry = null;
            if (int.TryParse(input, out entryId))
            {
                entry = this.entries.FirstOrDefault(e => e.Id == entryId);
                entry?.Execut();
            }

            if (entry == null)
            {
                Console.WriteLine("Invalid Input.");
            }

            Console.WriteLine();
            Console.WriteLine();

            this.Show();
        }
    }
票数 2
EN

Code Review用户

发布于 2019-02-15 20:08:25

我不是C#程序员,但以下是一些一般性的反馈:

你叫menu.MainMenu(),但没有动词!宾语是名词,方法应该是动词。也许可以给方法命名为DisplayMenuDispatchUserAction,或者某种表示活动正在发生的东西?

您的MainMenu方法似乎不处理无效输入。如果用户点击返回会发生什么?EOF?“Abcde”

我看到的失败模式只是递归地调用自己。所以,我可以用一系列9's作为输入来耗尽你的程序吗?放入一个while true循环,或者类似的东西。可能循环并调用内部方法,以获得较小的清晰代码。

Person构造函数还更新id计数器。更改它,以便独立地管理id。如果提供的话,可以使用可选参数并强制id计数器高于该值吗?

您有一些尴尬的代码来实现您的搜索。为什么您的比较逻辑在菜单类中,还是在第三方类中?我认为询问一个人的名字是否与字符串匹配是Person类应该处理的事情:

代码语言:javascript
复制
foreach (Person guy in people)  
     if (guy.isThisYou(target))
          etc.

我刚刚注意到,您通过递归处理到主菜单的所有返回。别干那事。返回并在主菜单中编写一个循环。

您有很多用于输入和输出的与控制台交互的模式。将它们转化为专用的辅助函数/方法。示例:打印两行换行符以分隔“段落”可以是NewParagraph();写一行然后读取一行可以是GetInput (String prompt)

如果可能的话,将输入流和输出流分离到变量中,并对这些流变量进行读写。这将使编写一些测试用例成为可能:用字符串流构造菜单,并将输出与输入的期望值进行比较。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/213535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档