Мини-приложение Банк


Сегодня я пошла на собеседование с cleartrip программного обеспечения компании. На первом этапе программирования, нам нужно построить мини-банка приложения.

В статье вопрос они четко отметили, что нет сохранение данных не требуется.

  • Создать учетную запись
  • Деньги
  • Снять деньги, честь ежедневный лимит на снятие.
  • Проверить баланс

Это то, что я сделал на мою собственную, и я получаю отклонены.

import java.util.Scanner;

public class CreateAccount {
    int accountid;
    String accountantname;
    String IFSCcode;

   public CreateAccount(int accountid,String accountantname,String IFSCcode){
    this.accountid = accountid;
    this.accountantname = accountantname;
    this.IFSCcode = IFSCcode;
   }

    /*//adding deposit money with the balance 
    public double despositMoney() throws MiniumAmountDeposit{

        double Currentbalance = 0.00;
        Scanner scn = new Scanner(System.in);
        System.out.println("please enter the deposit amount");
        double Depositamount = scn.nextDouble();
        Currentbalance += Depositamount ;
        System.out.println("your currentbalance="+Currentbalance);

        return Currentbalance;
    }*/

    //withdrawl money  and set daily withdrawl limit
    public void WithdrawMoney() throws InsufficientBalException, MiniumAmountDeposit{


        double Currentbalance = 0.00;
        Scanner deposit = new Scanner(System.in);
        System.out.println("please enter the deposit amount");
        double Depositamount = deposit.nextDouble();
        Currentbalance += Depositamount ;
        System.out.println("your currentbalance="+Currentbalance);

        /*double Currentbalanace = despositMoney();*/

        //setDaily Withdrawl limit
           final double setDailyLimit = 2500.00;     

            Scanner withDraw = new Scanner(System.in);
            System.out.println("please enter the withdraw amount");
            double WithdrawMoney =withDraw.nextDouble();


        if(Currentbalance < WithdrawMoney)
            System.out.println("you have less amount : your current balance is="+Currentbalance);

        else if (WithdrawMoney > setDailyLimit)
            System.out.println("you have entered amount exceed than daily limit : your dailyLimit="+setDailyLimit);

        else 
            Currentbalance -= WithdrawMoney;
            System.out.println("your current balance is="+Currentbalance);

    }


    /*public void setWithdrawlLimit()throws exceedLimit{
        Scanner scn = new Scanner(System.in);
        System.out.println("please enter the withdraw amount");
           double  enterAmount = scn.nextDouble();
        double DailysetLimit = 2500;

        if(enterAmount>DailysetLimit)
            System.out.println("you have exceed daily limit : your dailyLimit"+DailysetLimit);


    }*/

    public String toString(){

        return "accountid="+this.accountid + "accountantname="+this.accountantname + "IFSCcode="+this.IFSCcode;
    }



    public static void main(String[] args){
        CreateAccount account = new CreateAccount(1234455533,"samy","ICIC09");
        System.out.println("you have created account : " +account);
    /*  
        try {
            account.despositMoney();
        } catch (MiniumAmountDeposit e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/

        try {
            account.WithdrawMoney();
        } catch (InsufficientBalException | MiniumAmountDeposit e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        /*try {
            account.setWithdrawlLimit();
        } catch (exceedLimit e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

*/      
    }

}


4616
2
задан 25 февраля 2018 в 04:02 Источник Поделиться
Комментарии
5 ответов

Мне жаль слышать, что вы получили отказ - это не весело. Я пойду через построчно, с некоторых общих замечаний в конце.

Некоторые мои заметки будут помечены как рекомендации по стилю; они обычно имеют в виду общепринятые принципы Ява (соглашения об именовании и т. д.), поэтому я постараюсь указать, где я пытаюсь утверждать для данного стиля я лично вместо этого рекомендую дать общее правило.

import java.util.Scanner;

public class CreateAccount {

Стиль: классы должны быть, как правило, существительные, например, счета или может AccountCreator, потому что вы используете их в качестве объектов - так что разумнее иметь "учетную запись", чем "операции createaccount"

    int accountid;
String accountantname;
String IFSCcode;

Стиль: Ява почти всегда использует верблюда случае именования, так accountid должно быть accountID и accountantname accountantNameи т. д.

   public CreateAccount(int accountid,String accountantname,String IFSCcode){

Стиль: имена методов должны начинаться с маленькой буквы редактировать: это конструктор (мой плохой) и поэтому правильно назвал. Не конструктор методов должны начинаться с маленькой буквы.

    this.accountid = accountid;
this.accountantname = accountantname;
this.IFSCcode = IFSCcode;
}

/*//adding deposit money with the balance

Что этот комментарий должен был мне сказать? Функция вызывается depositMoney, поэтому я ожидаю, что он будет вносить деньги - вам не нужно, чтобы сказать мне это. Вместо этого, возможно, будет полезно разъяснить, что сумма вклада идет от ввода пользователя, или что возвращаемое значение означает

    public double despositMoney() throws MiniumAmountDeposit{

double Currentbalance = 0.00;
Scanner scn = new Scanner(System.in);
System.out.println("please enter the deposit amount");
double Depositamount = scn.nextDouble();
Currentbalance += Depositamount ;
System.out.println("your currentbalance="+Currentbalance);

return Currentbalance;
}*/

Этот метод немного занят, - было бы неплохо, если бы функции для получения данных от пользователя, был еще где-то (в отдельной функции), тем более, что вы должны использовать его для нескольких команд.

Кроме того, это действительно кажется Currentbalance (currentBalanceесли мы используем верблюд дела ;Р) должна быть объектной переменной.


В статье вопрос они четко отметили, что нет сохранение данных не требуется.

Но, я думаю, что они имели в виду это, не сохранение данных между программой казней (вам не нужно сохранять данные учетной записи в файл, когда программа выключается, и читать его обратно, когда он начинает снова). Это сделало бы намного больше смысла, чтобы отслеживать баланс пользователя во время выполнения программы, и проверить, например, что пользователь не может вывести больше денег, чем они имеют в их счета.

    //withdrawl money  and set daily withdrawl limit
public void WithdrawMoney() throws InsufficientBalException, MiniumAmountDeposit{

double Currentbalance = 0.00;
Scanner deposit = new Scanner(System.in);
System.out.println("please enter the deposit amount");
double Depositamount = deposit.nextDouble();
Currentbalance += Depositamount ;
System.out.println("your currentbalance="+Currentbalance);

/*double Currentbalanace = despositMoney();*/

Смотри выше, Примечание - мы, вероятно, не хотите, чтобы пользователь мог внести деньги перед каждым выводом.

        //setDaily Withdrawl limit
final double setDailyLimit = 2500.00;

Это постоянные конфигурации - он должен идти в верхней части класса, до методов. Если все пользователи должны иметь одинаковые снятие лимита, он должен быть объявлен staticтоже.

            Scanner withDraw = new Scanner(System.in);
System.out.println("please enter the withdraw amount");
double WithdrawMoney =withDraw.nextDouble();

if(Currentbalance < WithdrawMoney)
System.out.println("you have less amount : your current balance is="+Currentbalance);

else if (WithdrawMoney > setDailyLimit)
System.out.println("you have entered amount exceed than daily limit : your dailyLimit="+setDailyLimit);

else
Currentbalance -= WithdrawMoney;
System.out.println("your current balance is="+Currentbalance);

}

Эти проверки хороши, хорошую работу.

    /*public void setWithdrawlLimit()throws exceedLimit{
Scanner scn = new Scanner(System.in);
System.out.println("please enter the withdraw amount");
double enterAmount = scn.nextDouble();
double DailysetLimit = 2500;

if(enterAmount>DailysetLimit)
System.out.println("you have exceed daily limit : your dailyLimit"+DailysetLimit);

}*/

Я не понимаю, что эта функция для.

    public String toString(){

return "accountid="+this.accountid + "accountantname="+this.accountantname + "IFSCcode="+this.IFSCcode;
}

public static void main(String[] args){
CreateAccount account = new CreateAccount(1234455533,"samy","ICIC09");
System.out.println("you have created account : " +account);
/*
try {
account.despositMoney();
} catch (MiniumAmountDeposit e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/

try {
account.WithdrawMoney();
} catch (InsufficientBalException | MiniumAmountDeposit e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

/*try {
account.setWithdrawlLimit();
} catch (exceedLimit e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

В общем, вы не должны уходить автоматически TODOв представленном коде. Для интервью, я бы справилась с отъездом TODOс объяснением функциональности я желаю я мог бы реализовать, но не хватает времени.

*/      
}
}

И это конец, так, в целом: похоже, у вас есть хороший старт на проблему. Самые большие проблемы я вижу (в порядке важности (мое мнение) для код включен в качестве части приложения):


  1. Код выглядит немного поспешил. Так же, как в Лицом к лицу интервью, внешность имеет значение для кода, который будет прочитан и рассмотрен. Большие куски закомментированного кода без каких-либо объяснений, а также ошибочное / несогласованные схемы именования, не произвести хорошее впечатление.

  2. Мне кажется, что ты немного не уверен в программе. Это может помочь много, чтобы тщательно продумать ввода / вывода для каждой функции, и какие данные должны быть сохранены в переменных объекта, как вы пишете свой код - все это может изменить, как вы идете вперед и понять проблему больше. Это очень полезно документа (напишите в комментариях!) предположения вы делаете о том, как программа должна работать.

  3. Есть некоторые места, где вы отклоняться от установленных правил Ява. Ни одна компания не имеет точно такой же код в стиле (вот как Google для Java), но есть некоторые вещи (верблюд, например), которые очень центральный для данного языка. Не используя верблюда случае правильно, когда пишу Java-это сигнал о том, что вы не знаете Java очень хорошо - в зависимости от должности, на которую вы претендуете, это может или может не быть проблемой.

Самые большие мои предложения по улучшению: всегда представляют самое чистое код можно, постарайтесь следовать широкие, важные, правила, как язык должен выглядеть, так что это чисто рецензента, а также работу по написанию коротких, полезные замечания по сложные или интересные места в коде.

6
ответ дан 25 февраля 2018 в 05:02 Источник Поделиться

Жаль читать, что вы получили отказ. Давайте попробуем узнать что.

Прежде всего, постарайтесь быть последовательны в своих имен и следовать соглашениям об именах. У вас есть WithdrawMoney способ
внутри CreateAccount класс. А "команда" класс, как ваш CreateAccount как правило, на методе, которые соответствуют намерениях
(выполнить, выполнять, создать). Методы и параметры должны начинаться с строчных букв, IFSCcode должно быть
ifscCode и WithdrawMoney должно быть withdrawMoney. Это для конвенции и основные хорошие практики.

double Не самый лучший выбор, когда имеешь дело с деньгами, вы должны лучше использовать BigDecimal. Но в идеальном мире вы
может создать Money(unit, amount) тип.

Разделение

Ваш микс код бизнес-проблемы с инфраструктурой, чтение из командной строки ничего не делать в то же
классовая, как и та, что управлять счетом. Вы должны взглянуть на некоторые Commons узоры, как в MVC.

Я бы ввел один AccountsService С одного метода для каждого варианта использования :
+ Создать учетную запись: create():AccountId кажется странным, но так как нет никаких требований к созданию, мы сохранить ее
простой, вижу YAGNI.
+ Депозит денег: deposit(BigDecimal, AccountId):void
+ Вывести деньги, честь ежедневное снятие лимита: withdraw(BigDecimal, AccountId):void ^DailyWithdrawLimitExceededExecption
+ Проверить баланс: getBalance(AccountId):BigDecimal

Этот сервис будет использоваться для изоляции бизнес-логики. С другой стороны, BankingApplicationCli может быть использован для
работа с InputStream и OutputStream для того, чтобы вызывать методы AccountsService и печатать результаты. Шахты
будет простой класс с основным циклом. Первым шагом будет выбрать или создать учетную запись, то все действия будут
сделано на этот счет, как в банкомате.

Моделирование бизнес-концепций

Мне нравится делать это близко к ДДД; я бы ввел один Account что можно извлечь или сохранить
из AccountsRepository. Это Account бы один метод для каждого варианта использования с некоторым предварительные условия:

class Account {
public final AccountId id;

void deposit(BigDecimal amount) {
assert amount.signum()>0;
// ...
}
void withdraw(BigDecimal amount) throws DailyWithdrawLimitExceededExecption {
assert amount.signum()>0;
// ...
}
BigDecimal getBalance() {
// ...
}
}

Вы видите, что существует прямое соответствие между методами от Account и AccountsService. Служба будет просто
соблюдение условий, проверяя входы и делегировать методы Account. Это где вы делаете
связь между инфраструктурой и бизнес (репозиторий инфраструктуры, но позже вы Майе также добавить безопасности,
операций, ведение журнала, ..)

class AccountsService {
private final AccountsRepository repository;

void withdraw(BigDecimal amount, AccountId accountId) throws InvalidAmountException, DailyWithdrawLimitExceededExecption {
if ( amount.signum()<1 ) {
throw new InvalidAmountException(amount);
}
Account account = repository.get(accountId);
account.withdraw(amount);
repository.save(account);
}

BigDecimal getBalance(AccountId accountId) {
return repository.get(accountId).getBalance();
}
}

Обратите внимание, что я использую конвенций, которые используют команды для метода, который изменяет систему, но выглядит как геттеры при запросе
государства. Вам может не нравиться эта конвенций, но идея состоит в том, чтобы подчеркнуть важность конвенций и самостоятельно
документированный код.

Проектирование deposit и withdraw методы

Первая мысль, что я имел в виду, чтобы управлять одним изменяемым BigDecimal поле. Он хорошо работает на основании deposit
: this.balance = balance.add(amount) и отозвать. Но когда вам приходится иметь дело с дневной лимит, вещи
более сложное. Вы сможете провести дата и сумма ежедневного вывода, но другой путь ведет List из Operation
что есть время и сумму, deposit добавить new Operation(amount) а withdraw добавить одну
new Operation(amount.negate()).

Для вычисления ежедневного вывода, вы должны фильтровать все операции за текущий день, которые снимут
(сумма отрицательная) и просуммировать их. Баланс рассчитывается путем уменьшения все операции через дополнение.

public BigDecimal getBalance() {
return history.stream()
.map(e -> e.amount)
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
}

/**
* Decrease this account balance of the given amount
* @param amount a positive amount of money to remove from this balance. NotNull, GreaterThanZero
* @throws WithdrawLimitExceededException if the daily withdraw limit is exceeded. Can be checked
* via getWithdrawAmountOfToday()
*/
public void withdraw(BigDecimal amount) throws WithdrawLimitExceededException {
assert amount.signum()>0 : "withdraw amount must be positive";
BigDecimal foreseenDailyWithdraw = getWithdrawAmountOfToday().add(amount);
if ( getDailyLimit().compareTo(foreseenDailyWithdraw)<0 ) {
throw new WithdrawLimitExceededException(getDailyLimit());
}
history.add(new Operation(amount.negate()));
}

Тестирование

Отделив все, что вы можете легко проверить поведение Account и взаимодействий AccountsService. Единственный
вещи, что является сложным для проверки является вашим BakingApplicationCli.


Вы можете найти мое решение на https://github.com/gervaisb/stackexchange-codereview/tree/188306/src/main/java/q188306. Кроме того, я добавил один AccountFactory чтобы создать новый действующий Account. Этот
не делать многие вещи, но может развиваться во времени и изолировать процесс создания. Я решил добавить getDailyLimit
способ в Account так что мы можем себе представить, чтобы на abstract Account и много реализаций с разными лимитами.
Завод является идеальным местом для выбрать реализации.

2
ответ дан 26 февраля 2018 в 12:02 Источник Поделиться

Просто то, что другие не упоминал и это очень важно:

Осознание параллелизма, который может повредить неатомарных операций. Особенно ввод/вывод - это очень типично, рыбалка за упоминание проблем параллелизма. Atomic<BigDecimal>

Как doubleявляются неточными, лучше использовать BigDecimal: двойной 3.1 такой же, как 3.1000 но на самом деле может быть 3.0999994.

Однако, есть несколько вещей, которые другие люди уже говорилось, Я оставил его в этом. Для быстрого улучшения:


  • Следуйте конвенциям Ява, особенно Вт.Р.Т. название: методы и переменные начинаются с маленькой буквы.

  • Отдельное человеческое ввода/вывода от методов на объекты данных.

  • Обратить внимание на орфографию ("вклада"). Никто не хочет, чтобы его красивый код расширен идентификаторы, как serachKey (часто видел).

  • Думаю, что в данных структурах, если есть Account класс, добавить BigDecimal amount = new BigDecimal("0.00"); к нему.

1
ответ дан 27 февраля 2018 в 11:02 Источник Поделиться

Мои два цента.
Поэтому намерение Я понимаю, заключалась в создании банка приложения с определенными действиями Банка. То, что я чувствую, что этот код вы поделились-это не приложение, а программа, которая может выполнить указанные действия банка. Один из способов увидеть это, чтобы начать думать с точки зрения конечного пользователя.


  • Как мои пользователи будут использовать приложение ? Они будут использовать API-интерфейс ?

Если он должен быть API, то вы могли бы выбрать, чтобы это было весной загрузки микрослужб. Так как это будет самый простой вариант.

Тогда следующий будет архитектурный дизайн вашего приложения.
Действия банков, упомянутых в вышеуказанном вопросе ваши "домен".

Требования домена должны быть инкапсулированы от остального мира. (В собственных класса и пакета)
Требования домена потребуется функции / интеграция покрытия тестами.
Там должны быть модульные покрытия тестами, а также за услуги, которые вы создаете.

Наконец, вы, возможно, захотите, чтобы указать, как это приложение будет развернуто.
Скажем, используя Docker и Kubernetes. Под этим я подразумеваю, как вы будете обеспечивать быструю доставку изменений в приложение микрослужб.

Вот некоторые из ключевых вещей, которые я чувствую, они будут ожидать, когда они хотят создать приложение.

0
ответ дан 25 февраля 2018 в 07:02 Источник Поделиться

В дополнение к отличный ответ MyStackRunnethOver (особенно выпуск #3, стандарты кодирования):

Следует задуматься, почему это хорошая практика, чтобы придерживаться стандартов кодирования, просто необходимо учитывать следующее:

Постарайтесь выяснить, когда в последний System.out.println выполняется в коде:

if(Currentbalance < WithdrawMoney)
System.out.println("you have less amount ..");

else if (WithdrawMoney > setDailyLimit)
System.out.println("you have entered amount ..");

else
Currentbalance -= WithdrawMoney;
System.out.println("your current balance is ..");

Вы увидите, что последний System.out за пределами if .. else if .. else и выполняется в любом случае.

Это расходится с вашим отступ, который предполагает, что она должна принадлежать в else блок.

Это несоответствие между задуманным действием (выраженное вдавливание) и реальное поведение-это скорее всего, поднимет брови.

Сделайте себе одолжение и привыкнуть, используя фигурные скобки:

if(Currentbalance < WithdrawMoney) {
System.out.println("you have less amount ..");
} else if (WithdrawMoney > setDailyLimit) {
System.out.println("you have entered amount ..");
} else {
Currentbalance -= WithdrawMoney;
}
System.out.println("your current balance is ..");

(например, как описано в Гугле стиль руководства).

Это делает намерение ваш код немного понятнее..

0
ответ дан 27 февраля 2018 в 10:02 Источник Поделиться