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);
        // ...
    }
}

반복해서 참조하며 강제 형변환 예시

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);
    }
}

이벤트 핸들러의 반복 사용

  • 동일한 이벤트 핸들러를 사용하며, senderEquals 메서드로 판단

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)
{
    // ...
}

문자열 보간 사용

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;
}

#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;
    }
}

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 userId = ""; // X
string userId = string.Empty; // O

빈 문자열의 비교

if (userId != "")
{
}

if (userId != null && 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();
        }
    }
    
    ...
        

엑셀 파일 읽고 처리하기

단순히 파일 읽어와 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;
        }
    }
}
        

Last updated

Was this helpful?