简体   繁体   English

在 Main() 中保持模块化?

[英]Maintaining modularity in Main()?

I'm writing the simple card game "War" for homework and now that the game works, I'm trying to make it more modular and organized.我正在为家庭作业编写简单的纸牌游戏“战争”,现在游戏可以运行了,我正在努力使其更加模块化和有条理。 Below is a section of Main() containing the bulk of the program.下面是包含大部分程序的Main()部分。 I should mention, the course is being taught in C#, but it is not a C# course.我应该提一下,该课程正在 C# 中教授,但它不是 C# 课程。 Rather, we're learning basic logic and OOP concepts so I may not be taking advantage of some C# features.相反,我们正在学习基本逻辑和 OOP 概念,因此我可能无法利用 C# 的某些功能。

bool sameCard = true;

while (sameCard)
{
    sameCard = false;
    card1.setVal(random.Next(1,14));        // set card value
    val1 = determineFace(card1.getVal());   // assign 'face' cards accordingly
    suit = suitArr[random.Next(0,4)];       // choose suit string from array
    card1.setSuit(suit);                    // set card suit
    card2.setVal(random.Next(1,14));        // rinse, repeat for card2...
    val2 = determineFace(card2.getVal());    
    suit = suitArr[random.Next(0,4)];        
    card2.setSuit(suit);  

    // check if same card is drawn twice:

    catchDuplicate(ref card1, ref card2, ref sameCard); 
}
Console.WriteLine ("Player: {0} of {1}", val1, card1.getSuit());
Console.WriteLine ("Computer: {0} of {1}", val2, card2.getSuit());

// compare card values, display winner:

determineWinner(card1, card2);   

So here are my questions:所以这是我的问题:

  • Can I use loops in Main() and still consider it modular?我可以在 Main() 中使用循环并仍然认为它是模块化的吗?
  • Is the card-drawing process written well/contained properly?抽卡过程写得好/包含得当吗?
  • Is it considered bad practice to print messages in a method (ie: determineWinner() )?在方法中打印消息是否被认为是不好的做法(即: determineWinner() )?

I've only been programming for two semesters and I'd like to form good habits at this stage.我只学了两个学期的编程,我想在这个阶段养成良好的习惯。 Any input/advice would be much appreciated.任何输入/建议将不胜感激。

Edit:编辑:

catchDuplicate() is now a boolean method and the call looks like this: catchDuplicate() 现在是一个 boolean 方法,调用如下所示:

sameCard = catchDuplicate(card1, card2);

thanks to @Douglas.感谢@Douglas。

If the main problem of your homework is create a modular application, you must encapsulate all logic in specialized classes.如果您作业的主要问题是创建模块化应用程序,则必须将所有逻辑封装在专门的类中。 Each class must do only one job.每个 class 只能做一项工作。 Function that play with the card must be in a card class. Function that draw cards, should be another class. Function打出的牌必须是class中的一张牌。Function抽牌的应该是另一张class。

I think it is the goal of your homework, good luck!我认为这是你作业的目标,祝你好运!

Can I use loops in Main() and still consider it modular?我可以在 Main() 中使用循环并仍然认为它是模块化的吗?

Yes, you can.是的你可以。 However, more often than not, Main in OOP-programs contains only a handful of method-calls that initiate the core functionality, which is then stored in other classes.然而,OOP 程序中的Main通常只包含少数启动核心功能的方法调用,然后存储在其他类中。

Is the card-drawing process written well/contained properly?抽卡过程写得好/包含得当吗?

Partially.部分地。 If I understand your code correctly (you only show Main ), you undertake some actions that, when done in the wrong order or with the wrong values, may not end up well.如果我正确理解你的代码(你只显示Main ),你会采取一些行动,如果以错误的顺序或错误的值完成,可能不会很好地结束。 Think of it this way: if you sell your class library ( not the whole product, but only your classes), what would be the clearest way to use your library for an uninitiated user?这样想:如果你出售你的 class 库(不是整个产品,而只是你的类),对于一个没有经验的用户来说,使用你的库的最清晰的方式是什么?

Ie, consider a class Deck that contains a deck of cards.即,考虑包含一副纸牌的 class Deck On creation it creates all cards and shuffles it.在创建时,它会创建所有卡片并洗牌。 Give it a method Shuffle to shuffle the deck when the user of your class needs to shuffle and add methods like DrawCard for handling dealing cards.当你的 class 的用户需要洗牌时,给它一个Shuffle方法来洗牌,并添加像DrawCard这样的方法来处理发牌。

Further: you have methods that are not contained within a class of their own yet have functionality that would be better of in a class. Ie, determineFace is better suited to be a method on class Card (assuming card2 is of type Card ).此外:您有自己的 class 中未包含的方法,但具有 class 中更好的功能。即, determineFace更适合作为 class Card上的方法(假设card2的类型为Card )。

Is it considered bad practice to print messages in a method (ie: determineWinner())?在方法中打印消息是否被认为是不好的做法(即:determineWinner())?

Yes and no.是和不是。 If you only want messages to be visible during testing, use Debug.WriteLine .如果您只想在测试期间看到消息,请使用Debug.WriteLine In a production build, these will be no-ops.在生产构建中,这些将是空操作。 However, when you write messages in a production version, make sure that this is clear from the name of the method.但是,当您在生产版本中编写消息时,请确保从方法名称中清楚这一点。 Ie, WriteWinnerToConsole or something.即, WriteWinnerToConsole或其他东西。

It's more common to not do this because: what format would you print the information?这样做更为常见,因为:您将以何种格式打印信息? What text should come with it?它应该附带什么文字? How do you handle localization?你如何处理本地化? However, when you write a program, obviously it must contain methods that write stuff to the screen (or form, or web page).但是,当您编写程序时,显然它必须包含将内容写入屏幕(或表单,或 web 页面)的方法。 These are usually contained in specific classes for that purpose.为此目的,这些通常包含在特定的类中。 Here, that could be the class CardGameX for instance.在这里,例如,它可能是 class CardGameX

General thoughts一般想法
Think about the principle "one method/function should have only one task and one task only and it should not have side effects (like calculating square and printing, then printing is the side effect).".想想“一个方法/函数应该只有一个任务,只有一个任务,它不应该有副作用(比如计算平方打印,那么打印就是副作用)”的原则。

The principle for classes is, very high-level: a class contains methods that logically belong together and operate on the same set of properties/fields.类的原则是非常高层次的:class 包含逻辑上属于一起并在同一组属性/字段上运行的方法。 An example of the opposite: Shuffle should not be a method in class Card .相反的例子: Shuffle不应该是 class Card中的方法。 However, it would belong logically in the class Deck .但是,它在逻辑上属于 class Deck

Take all advices on "best practices" with a grain of salt.对所有关于“最佳实践”的建议持保留态度。 Always think for yourself.永远为自己着想。

That said:那说:

  • Can I use loops in Main() and still consider it modular?我可以在 Main() 中使用循环并仍然认为它是模块化的吗?

The two concepts are independent.这两个概念是独立的。 If your Main() only does high-level logic (ie calls other methods) then it does not matter if it does so in a loop, after all the algorithm requires a loop.如果您的 Main() 仅执行高级逻辑(即调用其他方法),那么它是否在循环中执行并不重要,毕竟算法需要循环。 (you wouldn't add a loop unnecessarily, no?) (你不会不必要地添加一个循环,不是吗?)

As a rule of thumb, if possible/practical, make your program self-documenting.作为一个经验法则,如果可能/实际的话,让你的程序自我记录。 Make it "readable" so, if a new person (or even you, a few months from now) looks at it they can understand it at any level.让它“可读”,这样,如果一个新人(甚至是你,几个月后)看到它,他们可以在任何层面上理解它。

  • Is the card-drawing process written well/contained properly?抽卡过程写得好/包含得当吗?

No. First of all, a card should never be selected twice.不,首先,一张牌永远不应该被选择两次。 For a more "modular" approach I would have something like this:对于更“模块化”的方法,我会有这样的事情:

while ( Deck.NumCards >= 2 )
{
   Card card1 = Deck.GetACard();
   Card card2 = Deck.GetACard();
   PrintSomeStuffAboutACard( GetWinner( card1, card2 ) );
}
  • Is it considered bad practice to print messages in a method (ie: determineWinner())?在方法中打印消息是否被认为是不好的做法(即:determineWinner())?

Is the purpose of determineWinner to print a message? determineWinner的目的是打印消息吗? If the answer is "No" then it is not a matter of "bad practice", you function is plain wrong.如果答案是“否”,那么这不是“不良做法”的问题,您 function 显然是错误的。

That said, there is such a thing as a "debug" build and a "release" build.也就是说,存在“调试”构建和“发布”构建之类的东西。 To aid you in debugging the application and figuring out what works and what doesn't it is a good idea to add logging messages.为了帮助您调试应用程序并确定哪些有效,哪些无效,添加日志消息是个好主意。

Make sure they are relevant and that they are not executed in the "release" build.确保它们是相关的,并且它们不会在“发布”版本中执行。

Q: Can I use loops in Main() and still consider it modular?问:我可以在 Main() 中使用循环并仍然认为它是模块化的吗?

A: Yes, you can use loops, that doesn't really have an impact on modularity. A:是的,你可以使用循环,这对模块化没有真正的影响。

Q: Is the card-drawing process written well/contained properly? Q:抽卡过程写得好/包含得当吗?

A: If you want to be more modular, turn DrawCard into a function/method. A:如果你想更模块化,把DrawCard变成一个函数/方法。 Maybe just write DrawCards instead of DrawCard, but then there's an optimization-versus-modularity question there.也许只写 DrawCards 而不是 DrawCard,但是那里有一个优化与模块化的问题。

Q: Is it considered bad practice to print messages in a method (ie: determineWinner())?问:在方法(即 determineWinner())中打印消息是否被认为是不好的做法?

A: I wouldn't say printing messages in a method is bad practice, it just depends on context.答:我不会说在方法中打印消息是不好的做法,它只是取决于上下文。 Ideally, the game itself doesn't handle anything but game logic.理想情况下,游戏本身只处理游戏逻辑。 The program can have some kind of game object and it can read state from the game object. This way, you could technically change the game from being text-based to being graphical.该程序可以有某种游戏 object,它可以从游戏 object 中读取 state。这样,您可以从技术上将游戏从基于文本的游戏更改为图形游戏。 I mean, that's ideal for modularity, but it may not be practical given a deadline.我的意思是,这对于模块化来说是理想的,但在截止日期前可能不切实际。 You always have to decide when you have to sacrifice a best practice because there isn't enough time.您总是必须决定何时因为没有足够的时间而必须牺牲最佳实践。 Sadly, this is all too often a common occurrence.可悲的是,这种情况经常发生。

Separate game logic from the presentation of it.将游戏逻辑与其呈现分开。 With a simple game like this, it's an unnecessary dependency.对于像这样的简单游戏,这是一种不必要的依赖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM