我是Java的初学者,我的问题是我的方法经常变得很长。有人告诉我方法应该尽可能简短,而一种方法只能做一件事情。例如,我制作了一个程序,可以在这里拍卖狗。我需要一些技巧,说明如何从这种较长的方法中分解出较小的方法,但仍然可以使其以相同的方式工作。这是我的代码:
private void makeNewBid() {
System.out.println("Enter the name of the user>");
String userName = input.nextLine().toLowerCase();
User u = getUser(userName);
if (userName == null || !userRegister.contains(u)) {
System.out.println("error. no such user");
return;
}else {
Auction bidAuction = null;
String name = dogLowerCaseTrim();
Dog d = getDog(name);
for(Auction a: auctionRegister ) {
if(auctionRegister.equals(name.toLowerCase())) {
bidAuction = a;
break;
}
}
Auction a = getAuctionedDog(d);
if(bidAuction != null) {
System.out.println("error. this dog is not up for auction.");
return;
}
System.out.print("Amount to bid: min " + (getAuctionedDog(d).getTopBid()+ 1 )+ "> ");
int amount = input.nextInt();
while(amount <= a.getTopBid()) {
System.out.println("error. too low bid");
System.out.println("Amount to bid: min " + (getAuctionedDog(d).getTopBid() + 1));
amount = input.nextInt();
}
Bid b = new Bid(u, amount);
getAuctionedDog(d).addBid(b);
System.out.println("Bid made");
input.nextLine();
}
}
答案 0 :(得分:1)
您的方法违反了single responsibility设计原则的一部分SOLID。
来自“清除代码”
大小
函数的第一个规则是它们应该很小。第二 功能规则是它们应该小于该值。
块和缩进
[...]函数的大小应不足以容纳嵌套结构。
做一件事
功能应该做一件事。他们应该做得很好。他们应该做 只能。
本书进一步介绍了一些保持功能清洁的内容,但我认为仅在示例中实现这些功能已经有些工作了。
最好创建一个服务来容纳所有这些方法。
不要那样停止您的方法流,而是创建您的异常并抛出该异常。
System.out.println("error. no such user");
return;
不要这样命名您的变量。取而代之的是使用有意义的变量名,这不仅可以提高代码的可读性,还可以为将来的自己,也可以为其他人提供。
Dog d = getDog(name);
答案 1 :(得分:0)
关于“有人告诉我方法应该尽可能短,而一种方法只能做一件事情”的问题。 这实际上是两个不同的语句:
对于第一句话:
通常,我会拒绝第一句话。编写方法的最短方法往往是一些难以理解的混淆代码垃圾。 但是,使代码更易于理解通常会导致更少的代码行。同样,如果您遵循第二条语句,您将得到较少的提示。 因此,尽管我认为尝试创建最少的代码行根本没有任何好处,但是如果可以改进代码,很多行会指示对代码进行复审(但复查本身不应该专注于代码行。有关代码的质量)。
第二句话:
此说法正确!一种方法应该专注于一项任务并正确地做到这一点。它应该具有尽可能小的副作用。
您称其为做某事。如果它还有其他功能,则很可能早晚为原始用途调用该问题。否则,您将无法在其他情况下调用它,因为它会执行您不想做的事情。
为清楚起见,具有明确目的的方法也易于理解和检查:它是否应做的事?还是做错了什么?如果您想确定的话,可以轻松地创建一个检查方法的测试。
现在为您提供代码: 首先,作为借口,您的示例“按原样”并不是显示方法的理想选择。此外,缺少某些部件,这些部件可能无法或不能提供进一步改进的空间。因此,不要单枪匹马,而要专注于底层思想,将您的代码分解为一些逻辑单元(按您的要求)。
a)您具有一些用户标识:
System.out.println("Enter the name of the user>");
String userName = input.nextLine().toLowerCase();
User u = getUser(userName);
if (userName == null || !userRegister.contains(u)) {
System.out.println("error. no such user");
return;
}
该标识似乎是可以用其自己的方法放置的逻辑单元。它标识一个用户。
b)您从其他地方定义的容器中获取了一些bidAuction:
for(Auction a: auctionRegister ) {
if(auctionRegister.equals(name.toLowerCase())) {
bidAuction = a;
break;
}
}
和平可以是一个单独的方法,该方法可以通过名称“ getBidAuction(String name)”来获取项目。
c)接下来,您要出价:
System.out.print("Amount to bid: min " + (getAuctionedDog(d).getTopBid()+ 1 )+ "> ");
int amount = input.nextInt();
while(amount <= a.getTopBid()) {
System.out.println("error. too low bid");
System.out.println("Amount to bid: min " + (getAuctionedDog(d).getTopBid() + 1));
amount = input.nextInt();
}
Bid b = new Bid(u, amount);
再次类似于可以放入返回出价的方法中的代码:“ Bid getBid(User user,Auction auction){”。
这样,您最终会得到结果-仍然不是最佳选择(缺少有关逻辑以及其他方法正在执行的操作的一些提示),但会分崩离析:
public class NewClass {
User identifyUser() {
System.out.println("Enter the name of the user>");
String userName = input.nextLine().toLowerCase();
User user = getUser(userName);
if (userName == null || !userRegister.contains(user)) {
System.out.println("error. no such user");
return null;
}
return user;
}
Auction findAuction(String name) {
Auction bidAuction = null;
for (Auction a : auctionRegister) {
if (auctionRegister.equals(name.toLowerCase())) {
return a;
}
}
return null;
}
Bid getBid(User user, Auction auction) {
System.out.print("Amount to bid: min " + (auction.getTopBid() + 1) + "> ");
int amount = input.nextInt();
while (amount <= auction.getTopBid()) {
System.out.println("error. too low bid");
System.out.println("Amount to bid: min " + (auction.getTopBid() + 1));
amount = input.nextInt();
}
return new Bid(user, amount);
}
void makeNewBid() {
User user = identifyUser();
if (null == user) {
return; //use an exception instead.
}
String name = dogLowerCaseTrim();
Auction bidAuction = findAuction(name);
//is this realy what you intended?!
if (bidAuction != null) {
System.out.println("error. this dog is not up for auction.");
return; //use an exception instead?
}
Dog dog = getDog(name);
//might this be the same as bidAuction?!
Auction auction = getAuctionedDog(dog);
Bid bid = getBid(user, auction);
auction.addBid(bid);
System.out.println("Bid made");
input.nextLine();
}
}
接下来出现的问题是,为什么用户再次为每个出价进行注册?那不应该在别的地方做吗?未注册用户甚至可能竞标吗?很可能应该在方法之外进行检查。
“拍卖”项目可能也是如此。取决于。
getAuctionedDog()有什么作用?是多余的吗?它类似于findAuction吗?那么“ bidAuction”和“ auction”是同一个对象吗? -无法从代码中说出来。如果没有:也许应该!如果是这样:使用您拥有的一个并删除第二个(在这种情况下,将其与多余的狗对象一起使用)。
逻辑上您想要的是比较“ if(bidAuction!= null){”吗? -我无法从您的代码中说出来,但很有可能您希望以另一种方式使用它“ if(bidAuction == null){”。