bad coding practice
멤버 정의 순서
클래스 내 모든 멤버는 "이벤트", "필드", "속성", "생성자", "메서드" 순서로 정의
public partial class SA_A2000 : BaseMenu
{
public SA_A2000()
{
InitializeComponent();
// ...
{
string strOrdnum = string.Empty; // 수주번호
bool isSaveChk = false; // 저장버튼 클릭시 변경
bool isMasterChk = false; // 기본정보 수정 여부
bool isDetailChk = false; // 상세정보 수정 여부
bool isNewChk = false; // 신규버튼 클릭시 변경
string ordNumbering = string.Empty; //범한산업 수주번호 채번 구분
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// ...
}
}
public partial class SA_A2000 : BaseMenu
{
#region Fields
private string _OrderNumber = string.Empty; // 수주번호
private bool _IsSaveChk = false; // 저장버튼 클릭시 변경
private bool _IsMasterChk = false; // 기본정보 수정 여부
private bool _IsDetailChk = false; // 상세정보 수정 여부
private bool _IsNewChk = false; // 신규버튼 클릭시 변경
private string _OrdNumbering = string.Empty; //범한산업 수주번호 채번 구분
#endregion
public SA_A2000()
{
InitializeComponent();
// ...
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// ...
}
}
반복해서 참조하며 강제 형변환 예시
private void ButtonEditEx_Click(object sender, EventArgs e)
{
string WorkType = string.Empty;
if (((SimpleButtonEx)sender).Equals(btnProd))
{
if (((SimpleButtonEx)sender).Tag.Equals("시작"))
WorkType = "START";
else if (((SimpleButtonEx)sender).Tag.Equals("종료"))
{
if(SessionInfo.ServiceId == "20200108002") // 세원시스템
{
WorkType = "END_SW";
}
else
WorkType = "END";
}
Func_P_PR_A3000_S(WorkType);
}
else if (((SimpleButtonEx)sender).Equals(btnMacStop))
{
if (((SimpleButtonEx)sender).Tag.Equals("비가동시작"))
{
if (fnStopEnd())
{
btnMacStop.Text = "비가동종료";
btnMacStop.Tag = "비가동종료";
};
}
else if (((SimpleButtonEx)sender).Tag.Equals("비가동종료"))
{
if(Func_P_PR_A3000_S("StopE"))
{
btnMacStop.Text = "비가동시작";
btnMacStop.Tag = "비가동시작";
}
}
}
int focusplace = gvwList.FocusedRowHandle;
Func_P_PR_A3000_Q("PLAN");
if (focusplace == 0 && gvwList.FocusedRowHandle == 0)
{
FocusedRowChanged(gvwList);
}
}
private void ButtonEditEx_Click(object sender, EventArgs e)
{
SimpleButtonEx simpleButton = sender as SimpleButtonEx;
if (simpleButton.Equals(btnProd))
{
//...
}
else if (simpleButton.Equals(btnMacStop))
{
//...
}
}
이벤트 핸들러의 반복 사용
동일한 이벤트 핸들러를 사용하며,
sender
를Equals
메서드로 판단
public partial class SY_TEST01 : BaseMenu
{
InitializeComponent();
grpTop.CustomButtonClick += GrpTop_CustomButtonClick;
grpFiles.CustomButtonClick += GrpFiles_CustomButtonClick;
}
private void GrpTop_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
// ...
}
private void GrpFiles_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
// ...
}
public partial class SY_TEST01 : BaseMenu
{
InitializeComponent();
grpTop.CustomButtonClick += GroupControlEx_CustomButtonClick;
grpFiles.CustomButtonClick += GroupControlEx_CustomButtonClick;
}
private void GroupControlEx_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
(sender as Control)?.Focus();
string tagValue = e.Button.Properties.Tag?.ToString() ?? string.Empty;
if (sender.Equals(grpTop))
{
// ...
}
else if (sender.Equals(grpFiles))
{
// ...
}
}
문자열 보간 사용
string execPc = GetClientPCName() + "/" + GetIPAddress();
string execPc = $"{GetClientPCName()}/{GetIPAddress()}";
반복해서 작성한 코드의 메서드화
GridFormatRule / FormatCondition.Expression
아래 예시는 데이터를 조회할때 마다 Rule을 새로 등록하는 패턴이며, 예시 코드처럼 Expression 속성의 값이 변하지 않는 문자열일 경우 [Grid Designer] 에서 등록하는게 맞습니다.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
gvwList.FormatRules.Add(gridFormatRule1);
// ...
// ...
gvwList.FormatRules.Add(gridFormatRule4);
}
public override void QueryClick()
{
fnQRY_P_SA200440_426_Q("Q");
AddGridRule();
// ...
// ...
AddGridRule4();
}
DevExpress.XtraGrid.GridFormatRule gridFormatRule1 = new DevExpress.XtraGrid.GridFormatRule();
DevExpress.XtraEditors.FormatConditionRuleValue formatConditionRuleValue1 = new DevExpress.XtraEditors.FormatConditionRuleValue();
private void AddGridRule()
{
gridFormatRule1.ApplyToRow = false;
gridFormatRule1.Column = coldlvday;
gridFormatRule1.Name = "Format0";
formatConditionRuleValue1.Appearance.Font = new System.Drawing.Font("돋움", 11F, System.Drawing.FontStyle.Bold);
formatConditionRuleValue1.Appearance.ForeColor = Color.Red;
formatConditionRuleValue1.Appearance.Options.UseFont = true;
formatConditionRuleValue1.Condition = DevExpress.XtraEditors.FormatCondition.Expression;
formatConditionRuleValue1.Expression = "[displayyn] > 0";
gridFormatRule1.Rule = formatConditionRuleValue1;
}
// ...
// ...
DevExpress.XtraGrid.GridFormatRule gridFormatRule4 = new DevExpress.XtraGrid.GridFormatRule();
DevExpress.XtraEditors.FormatConditionRuleValue formatConditionRuleValue4 = new DevExpress.XtraEditors.FormatConditionRuleValue();
private void AddGridRule4()
{
gridFormatRule4.ApplyToRow = false;
gridFormatRule4.Column = colday;
gridFormatRule4.Name = "Format0";
formatConditionRuleValue4.Appearance.Font = new System.Drawing.Font("돋움", 11F, System.Drawing.FontStyle.Bold);
formatConditionRuleValue4.Appearance.ForeColor = Color.Red;
formatConditionRuleValue4.Appearance.Options.UseFont = true;
formatConditionRuleValue4.Condition = DevExpress.XtraEditors.FormatCondition.Expression;
formatConditionRuleValue4.Expression = "[dday2] < 0";
gridFormatRule4.Rule = formatConditionRuleValue4;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public override void QueryClick()
{
fnQRY_P_SA200440_426_Q("Q");
// 등록된 Rule 초기화
gvwList.FormatRules.Clear(); /* 중요 */
// Rule 추가
AddExpressionRuleToGridView(
gvwList,
coldlvday,
"[displayyn] > 0",
font: new Font("돋움", 11F, FontStyle.Bold),
foreColor: Color.Red);
// ...
// ...
AddExpressionRuleToGridView(
gvwList,
coldlvday,
"[dday2] < 0",
font: new Font("돋움", 11F, FontStyle.Bold),
foreColor: Color.Red);
}
private void AddExpressionRuleToGridView(GridView view, GridColumn gridColumn, string expression,
bool applyToRow = false, Font font = null, Color? backColor = null, Color? foreColor = null)
{
var formatRule = new DevExpress.XtraGrid.GridFormatRule();
var conditionRuleValue = new DevExpress.XtraEditors.FormatConditionRuleValue();
conditionRuleValue.Condition = DevExpress.XtraEditors.FormatCondition.Expression;
conditionRuleValue.Expression = expression ?? string.Empty;
if (font != null)
conditionRuleValue.Appearance.Font = font;
if (backColor != null)
conditionRuleValue.Appearance.BackColor = (Color)backColor;
if (foreColor != null)
conditionRuleValue.Appearance.ForeColor = (Color)foreColor;
formatRule.Rule = conditionRuleValue;
formatRule.ApplyToRow = applyToRow;
formatRule.Column = gridColumn;
view.FormatRules.Add(formatRule);
}
#region 의 남용
region 전처리기는 필드나 프로퍼티 각 멤버의 지역을 구분해서 묶거나 유사한 기능의 여러 메서드를 묶어 코드를 정리하는 용도로 사용한다.
아래 예시처럼 region 블럭 내 하나의 메서드만 존재할 경우엔 사용하지 않는다.
#region [RESIZE]
private void MA300200_Resize(object sender, EventArgs e)
{
grpOutkind.Width = this.Width / 5 * 3;
}
#endregion
#region [ Merge Cell ]
private void gvwBandList_CellMerge(object sender, CellMergeEventArgs e)
{
GridView view = sender as GridView;
string lot1 = view.GetRowCellValue(e.RowHandle1, "s_lotnum").ToString();
string lot2 = view.GetRowCellValue(e.RowHandle2, "s_lotnum").ToString(); ;
e.Merge = lot1.Equals(lot2);
e.Handled = true;
}
#endregion
TabControl에서 현재 선택된 TabPage의 판단
나쁜 표현: 열거형을 정의하고 프로퍼티에 값을 할당하는 방식으로 처리한 뒤 해당 프로퍼티의 값으로 판단하는 방식
좋은 표현: XtraTabContorl.SelectedTabPage 속성의 값을 Equals 메서드를 이용해 판단 (이때 TabPage 개체의 이름이 코드만 보고도 어떤 Page 인지를 알 수 있도록 네이밍이 중요)
enum ProcessType
{
DayWork, //일용직일근태
DayAgg, //일용직집계표
DayInd //일용직 개인별명세서
}
ProcessType ActiveProcessType { get; set; }
private void TabControl_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e)
{
var tabControl = sender as XtraTabControl;
//[일용직일근태]
if (tabControl.SelectedTabPage.Equals(tpgList))
{
ActiveProcessType = ProcessType.DayWork;
}
//[일용직집계표]
else if (tabControl.SelectedTabPage.Equals(tpgSummary))
{
ActiveProcessType = ProcessType.DayAgg;
}
//[일용직 개인별명세서]
else if (tabControl.SelectedTabPage.Equals(tpgPersonal))
{
ActiveProcessType = ProcessType.DayInd;
}
QueryClick();
}
public override void PrintClick()
{
switch (ActiveProcessType)
{
case ProcessType.DayWork:
break;
case ProcessType.DayAgg:
if (textEditEx1.Text == "") return;
spreadsheetControl2.Print();
break;
case ProcessType.DayInd:
if (gvwEmpList.FocusedRowHandle < 0) return;
if (gvwEmpList.GetFocusedRowCellValue("Menu_ID").ToString() == "")
return;
spreadsheetControl3.Print();
break;
default:
break;
}
}
private void TabMain_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e)
{
QueryClick();
}
public override void PrintClick()
{
if (tabMain.SelectedTabPage.Equals(tpgSummary))
{
if (string.IsNullOrEmpty(textEditEx1.Text))
return;
spreadsheetControl2.Print();
}
else if (tabMain.SelectedTabPage.Equals(tpgPersonal))
{
if (gvwEmpList.FocusedRowHandle < 0 || string.IsNullOrEmpty(gvwEmpList.GetFocusedRowCellValue("Menu_ID")?.ToString()))
return;
spreadsheetControl3.Print();
}
}
CTS(Common Type System) 보단 기본 자료형 키워드를 사용 할 것
Int32 minute = 0; // X
int minute = 0; // O
Double.TryParse("3.14", out double number); // X
double.TryParse("3.14", out double number); // O
String str = "A"; // X
string str = "A"; // O
빈 문자열
""
대신 string.Empty
를 사용할 것
""
대신 string.Empty
를 사용할 것string userId = ""; // X
string userId = string.Empty; // O
빈 문자열의 비교
if (userId != "")
{
}
if (userId != null && userId != "")
{
}
if (string.IsNullOrEmpty(userId))
{
}
적절하지 못한 멤버 변수 선언과 조회 조건 파라미터 초기화
private DateTime _Today;
멤버 변수 정의 불필요. 필요시GetServerDateTime()
메서드 호출로 날짜를 받아와 처리하는게 좀 더 명확조회 조건을 초기화 하는
ResetParameters
메서드를 정리하여OnLoad
에서 호출
public partial class PR050320 : JERPBaseForm
{
private DateTime _Today;
public PR050320()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
DeleteButton = false;
PreviewButton = false;
PrintButton = false;
NewButton = false;
_Today = GetServerDateTime();
ymdfrdt.EditValue = GetDefault("Query", ymdfrdt, _Today.AddMonths(-1));
ymdtodt.EditValue = GetDefault("Query", ymdtodt, _Today);
radfinyn.EditValue = GetDefault("Query", radfinyn, "%");
cbolocation.EditValue = GetDefault("Query", cbolocation, SessionInfo.location);
ymdfrdt1.EditValue = GetDefault("Query", ymdfrdt1, _Today.AddMonths(-1));
ymdtodt1.EditValue = GetDefault("Query", ymdtodt1, _Today);
cbolocation1.EditValue = GetDefault("Query", cbolocation1, SessionInfo.location);
}
private void ResetParameters()
{
if (TabInOut.SelectedTabPage.Equals(tpgOut))
{
ymdfrdt.EditValue = GetDefault("Query", ymdfrdt, _Today.AddMonths(-1));
ymdtodt.EditValue = GetDefault("Query", ymdtodt, _Today);
cbolocation.EditValue = GetDefault("Query", cbolocation, SessionInfo.location);
radfinyn.EditValue = GetDefault("Query", radfinyn, "N");
}
else if (TabInOut.SelectedTabPage.Equals(tpgIn))
{
ymdfrdt1.EditValue = GetDefault("Query", ymdfrdt1, _Today.AddMonths(-1));
ymdtodt1.EditValue = GetDefault("Query", ymdtodt1, _Today);
cbolocation1.EditValue = GetDefault("Query", cbolocation1, SessionInfo.location);
}
}
private void GroupControl_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
(sender as Control).Focus();
string tagValue = e.Button?.Properties?.Tag?.ToString() ?? string.Empty;
if (tagValue.Equals("reset"))
{
InitControls(sender as Control);
ResetParameters();
}
}
...
public partial class PR050320 : JERPBaseForm
{
public PR050320()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
DeleteButton = false;
PreviewButton = false;
PrintButton = false;
NewButton = false;
ResetParameters(tpgOut);
ResetParameters(tpgIn);
}
private void ResetParameters(XtraTabPage tabPage)
{
DateTime today = GetServerDateTime();
if (tabPage.Equals(tpgOut))
{
ymdfrdt.EditValue = GetDefault("Query", ymdfrdt, today.AddMonths(-1));
ymdtodt.EditValue = GetDefault("Query", ymdtodt, today);
cbolocation.EditValue = GetDefault("Query", cbolocation, SessionInfo.location);
radfinyn.EditValue = GetDefault("Query", radfinyn, "N");
}
else if (tabPage.Equals(tpgIn))
{
ymdfrdt1.EditValue = GetDefault("Query", ymdfrdt1, today.AddMonths(-1));
ymdtodt1.EditValue = GetDefault("Query", ymdtodt1, today);
cbolocation1.EditValue = GetDefault("Query", cbolocation1, SessionInfo.location);
}
}
private void GroupControl_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
(sender as Control).Focus();
string tagValue = e.Button?.Properties?.Tag?.ToString() ?? string.Empty;
if (tagValue.Equals("reset"))
{
InitControls(sender as Control);
ResetParameters(tabInOut.SelectedTabPage);
}
}
...
엑셀 파일 읽고 처리하기
단순히 파일 읽어와 GridControl에 바인딩하기
읽어온 파일의 데이터를 GridView에 표현할 때 속도 저하를 개선한 예시
코드 내 속도 저하 문제가 되었던 부분에 주석 확인
Util 클래스의 ConvertExcelToDataTable 메서드 확인
private void FileOpen()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = false;
ofd.Filter = "Excel Files(.xlsx)|*.xlsx|Excel Files(.xls)|*.xls|Excel Files(.xlsm)|*.xlsm|Excel Files(*.xml)|*.xml|Excel Files(*.xlt)|*.xlt|Excel Files(.xltx)|*.xltx";
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
if (ofd.FileName != string.Empty)
{
Workbook workBook = new Workbook();
if (Path.GetExtension(ofd.FileName) == ".xls")
{
workBook.LoadDocument(ofd.FileName, DocumentFormat.Xls);
}
else if (Path.GetExtension(ofd.FileName) == ".xlsx")
{
workBook.LoadDocument(ofd.FileName, DocumentFormat.Xlsx);
}
else
{
ShowMessageBox("파일의 확장자명을 확인하여 주십시오.");
return;
}
Range range = workBook.Worksheets[0].GetUsedRange();
DataTable dt = workBook.Worksheets[0].CreateDataTable(range, false);
int colcnt = 0;
colcnt = 22;
if (workBook.Worksheets[0].Columns.LastUsedIndex != colcnt)
{
ShowMessageBox(GetFormMessage("BA_A0051_470_002", "업로드 양식을 확인하여 주십시오."));
return;
}
/*******************************************************************************************
* 이 부분에서 읽어 들인 엑셀 파일에 모든 Cell을 반복하며 처리하기에
* Row가 많을수록 매우 많은 시간이 소요됨
*******************************************************************************************/
int rowcnt = 0;
rowcnt = 1;
for (int i = rowcnt; i < workBook.Worksheets[0].Rows.LastUsedIndex + 1; i++)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < workBook.Worksheets[0].Columns.LastUsedIndex + 1; j++)
{
dr[j] = workBook.Worksheets[0].Cells[i, j].DisplayText;
}
dt.Rows.Add(dr);
}
/******************************************************************************************/
/*******************************************************************************************
* 많은 양(1천건 이상)의 DataRow를 참조하여 GridView에 행을 추가후
* GridView를 참조하여 Cell에 하나씩 값을 넣어줄 경우 많은 시간이 소요됨
*******************************************************************************************/
if (dt != null)
{
foreach (DataRow drResult in dt.Rows)
{
GridAddNewRow(grdList2, gvwList2.RowCount);
int row = gvwList2.FocusedRowHandle;
gvwList2.SetRowCellValue(row, "ROOTITEM", drResult["Column1"].ToString());
gvwList2.SetRowCellValue(row, "ROOTITEMDESC", drResult["Column2"].ToString());
gvwList2.SetRowCellValue(row, "ROOTITEMDRAW", drResult["Column3"].ToString());
gvwList2.SetRowCellValue(row, "LVL", drResult["Column4"].ToString());
gvwList2.SetRowCellValue(row, "PARENTITEM", drResult["Column5"].ToString());
gvwList2.SetRowCellValue(row, "PARENTITEMDESC", drResult["Column6"].ToString());
gvwList2.SetRowCellValue(row, "DRAW", drResult["Column7"].ToString());
gvwList2.SetRowCellValue(row, "COMPONENT", drResult["Column8"].ToString());
gvwList2.SetRowCellValue(row, "COMPDESC1", drResult["Column9"].ToString());
gvwList2.SetRowCellValue(row, "DRAW2", drResult["Column10"].ToString());
gvwList2.SetRowCellValue(row, "QTYPERBOM", drResult["Column11"].ToString());
gvwList2.SetRowCellValue(row, "UM", drResult["Column12"].ToString());
gvwList2.SetRowCellValue(row, "STATUS", drResult["Column13"].ToString());
gvwList2.SetRowCellValue(row, "SFTY_STK", drResult["Column14"].ToString());
gvwList2.SetRowCellValue(row, "ORD_MAX", drResult["Column15"].ToString());
gvwList2.SetRowCellValue(row, "ORD_MIN", drResult["Column16"].ToString());
gvwList2.SetRowCellValue(row, "ORD_MULT", drResult["Column17"].ToString());
gvwList2.SetRowCellValue(row, "LOC", drResult["Column18"].ToString());
gvwList2.SetRowCellValue(row, "PROD_LINE", drResult["Column19"].ToString());
gvwList2.SetRowCellValue(row, "PUR_LEAD", drResult["Column20"].ToString());
gvwList2.SetRowCellValue(row, "GROUPNO", drResult["Column21"].ToString());
gvwList2.SetRowCellValue(row, "MFG_LEAD", drResult["Column22"].ToString());
gvwList2.SetRowCellValue(row, "SUPPLIER", drResult["Column23"].ToString());
}
}
/******************************************************************************************/
}
}
catch (Exception ex)
{
ShowMessageBox(string.Format(GetFormMessage("BA_A0051_470_001", "파일을 업로드 할 수 없습니다."), ex));
return;
}
}
}
// 클래스 전역 멤버
// 읽어 들인 엑셀 파일의 컬럼 순서에 맞게 선언
// (GridControl에 바로 바인딩 하기 위함)
private string[] _DataColumnNames =
{
"ROOTITEM",
"ROOTITEMDESC",
"ROOTITEMDRAW",
"LVL",
"PARENTITEM",
"PARENTITEMDESC",
"DRAW",
"COMPONENT",
"COMPDESC1",
"DRAW2",
"QTYPERBOM",
"UM",
"STATUS",
"SFTY_STK",
"ORD_MAX",
"ORD_MIN",
"ORD_MULT",
"LOC",
"PROD_LINE",
"PUR_LEAD",
"GROUPNO",
"MFG_LEAD",
"SUPPLIER"
};
private void BindingDataFromExcelFile()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = false;
ofd.Filter = "Excel Files(.xlsx)|*.xlsx|Excel Files(.xls)|*.xls|Excel Files(.xlsm)|*.xlsm|Excel Files(*.xml)|*.xml|Excel Files(*.xlt)|*.xlt|Excel Files(.xltx)|*.xltx";
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
// 엑셀 파일의 데이터를 DataTable 형태로 반환
DataTable excelDatas = Util.ConvertExcelToDataTable(ofd.FileName, 0);
// 결과 DataTable의 DataColumn의 ColumnName을 변경
// (바인딩 할 GridControl의 GridColumn.FieldName 과 동일하게)
for (int i = 0; i < excelDatas.Columns.Count; i++)
{
excelDatas.Columns[i].ColumnName = _DataColumnNames[i];
}
// 데이터 바인딩
SetData(grdList2, excelDatas);
}
catch (Exception ex)
{
ShowMessageBox(string.Format(GetFormMessage("BA_A0051_470_001", "파일을 업로드 할 수 없습니다."), ex));
return;
}
}
}
Last updated
Was this helpful?