Как отделить логику от реализации

Ответить
johhy
Сообщения: 8
Зарегистрирован: 29 ноя 2012, 10:46
Откуда: RU Novosibirsk

Как отделить логику от реализации

Сообщение johhy » 27 дек 2012, 19:10

Добрый день!
Написал простейший калькулятор ( всегда его пишу на для освоения темы) в java начинающий
Отрывок исходного кода
public class MyActivity extends Activity implements View.OnClickListener{
TextView showTable;
int [] list={R.id.btn_1,R.id.btn_2,R.id.btn_3,R.id.btn_4,R.id.btn_5,R.id.btn_6,R.id.btn_7,R.id.btn_8,
R.id.btn_9,R.id.btn_0,R.id.btn_dot,R.id.btn_result,R.id.btnClear,R.id.btnDelete,R.id.btnUndo,
R.id.btnExit,R.id.btn_plus,R.id.btn_minus,R.id.btn_umnozh,R.id.btn_delenie};
Intent intent;
public String buf="0",sbuf="",fbuf="",undo="";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showTable=(TextView)findViewById(R.id.showTable);
for(int x:list) findViewById(x).setOnClickListener(this);
} //Intilisize activity

@Override
public void onClick(View view) {
int keys=33;
switch (view.getId()){
case R.id.btnClear:keys=16;break;
case R.id.btnDelete:keys=17;break;
case R.id.btnUndo:keys=18;break;
case R.id.btnExit:finish();
case R.id.btn_plus:keys=11;break;
case R.id.btn_minus:keys=12;break;
case R.id.btn_umnozh:keys=13;break;
case R.id.btn_delenie:keys=14;break;
case R.id.btn_result:keys=15;break;
case R.id.btn_1:keys=1;break;
case R.id.btn_2:keys=2;break;
case R.id.btn_3:keys=3;break;
case R.id.btn_4:keys=4;break;
case R.id.btn_5:keys=5;break;
case R.id.btn_6:keys=6;break;
case R.id.btn_7:keys=7;break;
case R.id.btn_8:keys=8;break;
case R.id.btn_9:keys=9;break;
case R.id.btn_0:keys=0;break;
case R.id.btn_dot:keys=10;break;
}
findKeys(keys);
} //Catch press key

private void findKeys(int key) {
switch (key){
case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:
num(key);break;
case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:
fun(key);break;
}
} //Filter keys - Fun or Num

private void fun(int key) {
switch (key){
case 16:buf="0";showBuf();undo="";fbuf="";sbuf="";
break;//Clear key
case 17:buf=showTable.getText().toString();
if(!buf.equalsIgnoreCase("0")) {
pushInUndo(buf);
buf=removeEndChar(buf);
if(buf.equalsIgnoreCase("")) buf="0";
showBuf();
}
break;//Delete key
case 18:if(!undo.equalsIgnoreCase("")){buf=undoChar(buf);showBuf();}
break;//Undo key
case 11: arif("+");
break;//Plus key
case 12: arif("-");
break;//Minus key
case 13: arif("*");
break;//Umnozh key
case 14: arif("/");
break;//Delenie key
case 15: arif("=");
break;//Result key
}
} //Fun keys

private void arif(String s) {
if((!sbuf.equalsIgnoreCase(""))&(!fbuf.equalsIgnoreCase(""))){
Float s1=Float.valueOf(sbuf);
Float s2=Float.valueOf(showTable.getText().toString());
if(fbuf.equalsIgnoreCase("+")) {s1=s1+s2;obrez(s1);}
if(fbuf.equalsIgnoreCase("-")) {s1=s1-s2; obrez(s1);}
if(fbuf.equalsIgnoreCase("*")) {s1=s1*s2; obrez(s1);}
if(fbuf.equalsIgnoreCase("/")){
if(s2!=0) {s1=s1/s2;obrez(s1);}
else {Toast.makeText(this,"Error: Divide ziro:"+sbuf+"/0",Toast.LENGTH_LONG).show();
sbuf="";fbuf="";buf="0"; return;
}
}
fbuf="";sbuf="";showBuf();buf="0";
}else{
if(fbuf.equalsIgnoreCase("=")){
fbuf="";sbuf="";return;
}
sbuf=showTable.getText().toString();
fbuf=s;
buf="0";
}


}

private void obrez(Float s1) {
String gt;
int qq=0;
qq=(int)(s1-qq);
if((s1-qq)!=0) gt=String.valueOf(s1); else gt=String.valueOf(qq);
buf="";
int j=gt.length();
if(j>10) j=10;
for(int i=0;i<j;i++) buf+=gt.charAt(i);
if(String.valueOf(s1).length()>10) Toast.makeText(
this,"Result more than 10 digits of screen.Show only 10 first digits of result!",Toast.LENGTH_LONG).show();
}


private void pushInUndo(String asd) {
if (asd.charAt(asd.length()-1)!='.') {
undo+=String.valueOf(asd.charAt(asd.length()-1));
}
} // Push char in buffer "undo" from "buf"

private String undoChar(String asd) {
if((buf.equalsIgnoreCase("0"))&(!undo.equalsIgnoreCase(""))){
asd="";
}
asd+=undo.charAt(undo.length()-1);
undo=removeEndChar(undo);
return asd;
} //Pop char from buffer "undo" to "buf"

private String removeEndChar(String asd) {
String s="";
for(int i = 0;i<asd.length()-1;i++) s+=asd.charAt(i);
return s;
} //Method remove end char in string

private void showBuf() {
showTable.setText(buf);
} //Method show "buf"

private void num(int key) {
if(buf.length()>=10) return;
if((buf.contains("."))&(key==10)) return;
if(buf.equalsIgnoreCase("0")&(key>=0)&(key<10)) buf="";
showKey(key);

} //Num keys

private void showKey(int key) {
if(key==10) buf=buf+".";
else buf=buf+String.valueOf(key);
showBuf();
} //Method show Num key

Понимаю что какойто быдло код те потом чтобы доьавить новые возможности нужно будет переделывать полностью код
Желание выделить логику кудато чтобы легко модифицировть код-добавть кнопки или функциональность итп
Вопрос
1.возможно ли константы типа R.id.btn.... разместит в enum-где тот тут читал что ненужно делать-почему?или запихать в Map-для перевода констант в читаемый вид и затем в отдельных классах с ними работать например Map<String,Integer>
2.может разделить код на классы-экран клвиатура и арифмометр которые взиамодествуют с активити

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как отделить логику от реализации

Сообщение rezak90 » 27 дек 2012, 20:10

о господи, не пытался даже вникнуть потому что нету здесь логики)))
1) зачем использовать вообще айди кнопок? зачем их хранить тогда когда они есть в ресурснике?
2) о боже, название переменных... delenie и т.д. или название айди кнопок точно не помню... не должно быть русских слов на латинице, всё пишется английским
3) первое что попалось это сравнение строк, в андроиде есть TextUtils (если не ошибаюсь с названием), а не привычные джавовские equals и т.д.
4) второе что попалось это зачем то хешмапы и т.д., не стал разбираться зачем но не думаю что они нужны в таком простом приложении как калькулятор, видимо с логикой перемудрили
5) далее не смотрел так как логика здесь велосипедная.

на счёт распихать всё по отдельным классам это правильно, но калькулятор не такое великое приложение что бы разграничивать его на классы, есть два числа над которыми следует выполнить арифм. операции и всё, всё просто
R.id.team
Политика на форуме запрещена

johhy
Сообщения: 8
Зарегистрирован: 29 ноя 2012, 10:46
Откуда: RU Novosibirsk

Re: Как отделить логику от реализации

Сообщение johhy » 28 дек 2012, 14:49

rezak90 Спасибо за критику.
1.Если вы про list c Id это я сделал чтобы автоматом прописать
for(int x:list) findViewById(x).setOnClickListener(this); и при добавлении или удалении кнопок не париться и смотрится компактно
Другого способа не пришло в голову( тогда может в отдельный класс выпихнуть?
2.Торопился и писал что в голову прийдёт-будем исправляться
3.Смотрел TextUtils да есть - буду пробовать
4.ХэшМапов в коде нет я просто спросил про них?
Я начинающий учусь пока)Вот прочитал http://skipy.ru/philosophy/cqComponents.html буду пытаться в этом направлении развиваться желание сделать максимально простой код для чтения
А на счет разделения в таком простом приложении как калькулятор-постараюсь точнее выразиться
Чтобы отдельно можно было например поменять "арифмометр"(логику ещё чтото) или сами активити с разными лэйаутами итп без глобального перелопачивания кода незнаю понятно ли я выразился

Ответить