논리적으로 절차적인 소프트웨어를 OO 언어로 작성하는 가장 깨끗한 방법


12

나는 전기 기술자이고 내가 무슨 짓을하는지 모르겠습니다. 내 코드의 미래 관리자를 저장하십시오.

최근에는 기능이 논리적으로 "절차 적"인 여러 개의 작은 프로그램 (C #)을 작업하고 있습니다. 예를 들어, 그중 하나는 다른 데이터베이스에서 정보를 수집하고 해당 정보를 사용하여 일종의 요약 페이지를 생성 한 후 인쇄 한 다음 종료하는 프로그램입니다.

이 모든 것에 필요한 논리는 약 2000 라인입니다. 나는 확실히 그 모든 것을 하나의 것으로 채우고 이전의 일부 개발자들이했던 것처럼 main()"정리"하고 싶지 않다 #region.

다음은 내가 만족스럽게 시도하지 않은 것들입니다.

DatabaseInfoGetter, SummaryPageGenerator 및 PrintUtility와 같이 거친 각 기능에 대해 정적 유틸리티를 만듭니다. 주요 기능을 다음과 같이 표시하십시오.

int main()
{
    var thisThing = DatabaseInfoGetter.GetThis();
    var thatThing = DatabaseInfoGetter.GetThat();
    var summary = SummaryPageGenerator.GeneratePage(thisThing, thatThing);

    PrintUtility.Print(summary);
}

하나의 프로그램을 위해 나는 심지어 인터페이스와 함께 갔다

int main()
{
    /* pardon the psuedocode */

    List<Function> toDoList = new List<Function>();
    toDoList.Add(new DatabaseInfoGetter(serverUrl));
    toDoList.Add(new SummaryPageGenerator());
    toDoList.Add(new PrintUtility());

    foreach (Function f in toDoList)
        f.Do();
}

이 중 어느 것도 옳지 않다. 코드가 길어짐에 따라이 두 가지 접근 방식이 모두 추악 해지기 시작합니다.

이와 같은 것을 구성하는 좋은 방법은 무엇입니까?


2
나는 이것이 완전히 중복인지 확실하지 않지만 많은 매개 변수가있는 단일 메소드 대 순서대로 호출 해야하는 많은 메소드 를 읽으십시오 .


@Snowman은 더 큰 코드 조각을 처음 쓰는 사람으로서 이러한 유형의 문제를 겪는 유일한 사람이 아니라는 것을 확신합니다. 그 질문에 대한 당신의 대답이 마음에 들었습니다. 도움이됩니다.
Lombard

@Lombard 복잡성을 관리 가능한 수준으로 줄이는 아이디어는 개발하기에 정말 좋은 기술입니다. 슈퍼맨조차도 큰 코드 기반을 이해할 수있는 사람 은 없습니다. 아이디어를 간단하게 표현하고 코드를 자체 문서화하는 방법을 찾는 것이 중요합니다.

"최근에 나는 기능이 논리적으로"절차 적 "인 여러 개의 작은 프로그램 (C #에서)으로 작업하고있다. 페이지를 인쇄 한 다음 종료합니다. ":"프로 시저 "와"제국 "을 혼동하지 않습니까? 절차 적 및 객체 지향적 둘 모두는 필수적 일 수있다. 즉, 이들은 순서대로 수행 될 동작을 표현할 수있다.
Giorgio

답변:


18

당신은 전문 프로그래머가 아니므로 단순성을 고수하는 것이 좋습니다. 프로그래머가 잘못 작성된 OO 프로그램을 수정하는 것보다 모듈화 된 절차 코드를 취하여 나중에 OO로 만드는 것이 훨씬 쉬울 것입니다. 당신이 경험이 없다면, 당신이나 당신을 따르는 사람에게 도움이되지 않는 부정한 혼란으로 변할 수있는 OO 프로그램을 만들 수 있습니다.

첫 번째 본능의 첫 번째 본능, "이것-그것"코드가 올바른 궤도라고 생각합니다. 무엇을하고 싶은지 분명하고 분명합니다. 코드 효율성에 대해 너무 걱정하지 마십시오. 명확성이 훨씬 중요합니다.

코드 세그먼트가 너무 길면 각각 고유 한 기능을 가진 한 입 크기의 덩어리로 나눕니다. 너무 짧은 경우 더 적은 모듈을 사용하고 더 많은 라인을 배치하십시오.

---- 포스트 스크립트 : OO 디자인 트랩

OO 프로그래밍으로 성공적으로 작업하는 것은 까다로울 수 있습니다. 전체 모델에 결함이 있다고 생각하는 사람들 도 있습니다 . Thinking in Java (현재 4 판) 라는 OO 프로그래밍을 처음 배울 때 사용한 훌륭한 책이 있습니다 . 동일한 저자가 C ++에 해당하는 책을 가지고 있습니다. 실제로 객체 지향 프로그래밍의 일반적인 함정을 다루는 프로그래머에게는 또 다른 질문이 있습니다 .

일부 함정은 정교하지만 기본적인 방법으로 문제를 만드는 방법은 많이 있습니다. 예를 들어, 몇 년 전에 내가 상속 일부 소프트웨어의 첫 번째 버전을 썼다 내 회사에서 인턴이 있었다 그는 모든 것을위한 인터페이스를 만든 언젠가 여러 구현이 있습니다. 물론 98 %의 경우에는 단일 구현 만 있었으므로 코드에 사용되지 않은 인터페이스가로드되어 인터페이스 호출을 다시 수행 할 수 없기 때문에 디버깅이 매우 성가신 것으로 나타났습니다. 구현에 대한 텍스트 검색 (지금은 IntelliJ를 사용했지만 "모든 구현 표시"기능이 있었지만 그 당시에는 없었습니다.) 여기서의 규칙은 절차 적 프로그래밍과 동일합니다. 항상 한 가지 하드 코딩. 둘 이상의 항목이있는 경우에만 추상화를 작성하십시오.

Java Swing API에서도 비슷한 종류의 디자인 오류가 있습니다. 그들은 스윙 메뉴 시스템에 게시-구독 모델을 사용합니다. 이것은 Swing에서 메뉴를 만들고 디버깅하는 것을 완전히 악몽으로 만듭니다. 아이러니는 완전히 무의미하다는 것입니다. 여러 기능이 메뉴 클릭을 "구독"해야하는 상황은 거의 없습니다. 또한 메뉴 시스템이 항상 항상 사용되기 때문에 publish-subscribe가 완전히 잘못되었습니다. 함수가 구독하고 무작위로 구독 취소하는 것과는 다릅니다. Sun의 "전문적인"개발자가 이와 같은 실수를 저질렀다는 사실은 전문가가 OO 디자인에서 기념비적 인 나사를 만드는 것이 얼마나 쉬운지를 보여줍니다.

나는 OO 프로그래밍에 대한 수십 년의 경험을 가진 매우 전문적인 개발자이지만, 모르는 톤이 있다는 것을 처음으로 인정할 것입니다. 나는 특정 디자인을 수행하는 방법에 대해 OO 열성 자였던 동료의 긴 강의를 들었습니다. 그는 자신이 무엇을하고 있는지 알았지 만, 정직하게 말하면 그의 정교한 디자인 모델을 가지고 있었기 때문에 그의 프로그램을 이해하는 데 어려움을 겪었습니다.


1
"명확성이 효율성보다 훨씬 중요합니다"
Stephen

"잘못 작성된 OO 프로그램"을 구성하는 내용을 설명하는 링크를 알려주거나 편집에 그 정보를 추가 할 수 있습니까?
Lombard

@ Lombard 내가 그랬어.
Tyler Durden

1

첫 번째 방법은 좋습니다. C와 같은 절차 적 언어에서 표준 접근 방식은 기능을 네임 스페이스로 나누는 DatabaseInfoGetter것입니다. 정적 클래스를 사용 하는 것은 기본적으로 동일합니다. 분명히이 접근법은 모든 것이 메소드로 분류되어 있어도 모든 것을 하나의 클래스로 밀어 넣는 것보다 더 간단하고 모듈화되고 읽기 쉽고 유지 관리 가능한 코드로 이어집니다.

말하자면, 가능한 한 적은 작업을 수행하도록 메소드를 제한하십시오. 일부 프로그래머는 조금 더 세분성을 선호 하지만 거대한 방법은 항상 유해한 것으로 간주됩니다.

여전히 복잡성으로 어려움을 겪고 있다면 프로그램을 더 세분화해야 할 것입니다. 계층 구조에서 더 많은 레벨을 작성하십시오 . DatabaseInfoGetter다른 클래스 ProductTableEntry나 이와 유사한 클래스를 참조해야 할 수도 있습니다. 절차 코드를 작성하고 있지만 C #을 사용하고 있다는 점을 기억하십시오. OOP는 다음과 같이 복잡성을 줄이는 여러 가지 도구를 제공합니다.

int main() 
{
    var thisthat = Database.GetThisThat();
}

public class ThisThatClass
{
    public String This;
    public String That;
}

public static class Database 
{
    public ThisThatClass GetThisThat()
    {
        return new ThisThatClass 
        {
            This = GetThis(),
            That = GetThat()
        };
    }

    public static String GetThis() 
    { 
        //stuff
    }
    public static String GetThat() 
    { 
        //stuff
    }

}

또한 정적 클래스에주의하십시오. 데이터베이스 클래스는 좋은 후보입니다. 일반적으로 데이터베이스가 하나만 있으면 아이디어를 얻을 수 있습니다.

궁극적으로 수학 함수를 생각하고 C #이 자신의 스타일에 맞지 않으면 Scala, Haskell 등과 같은 것을 시도하십시오.


0

나는 4 년 늦게 응답하고 있지만 OO 언어로 절차 적 일을하려고 할 때 반 패턴을 연구하고 있습니다. 그것은 당신이해야 할 일이 아닙니다! 이 반 패턴을 다루고 해결책을 보여주는 블로그를 찾았지만 많은 리팩토링과 사고 방식의 변화가 필요합니다. 자세한 내용 은 객체 지향 코드의 절차 코드 를 참조하십시오.
"this"와 "that"을 언급했듯이 기본적으로 두 개의 다른 클래스가 있다고 제안합니다. 이 클래스 (나쁜 이름!)와 그 클래스. 그리고 당신은 이것을 번역 할 수 있습니다 :

var summary = SummaryPageGenerator.GeneratePage(thisThing, thatThing);

이것으로 :

var summary = SummaryPageGenerator.GeneratePage(new This(DatabaseInfoGetter), new That(DatabaseInfoGetter));

이제 2,000 줄 이상의 절차 코드를보고 다양한 부분을 개별 클래스로 그룹화하고 다양한 절차를 해당 클래스로 이동시키는 방법을 결정하는 것이 흥미로울 것입니다.
각 수업은 단순해야하며 한 가지 일에만 집중해야합니다. 그리고 코드의 일부 부분이 이미 슈퍼 클래스를 처리하고 있으며 실제로는 너무 커서 유용하지 않습니다. 예를 들어 DatabaseInfoGetter는 혼란스러워 보입니다. 어쨌든 무엇을 얻고 있습니까? 너무 일반적인 소리입니다. 그러나 SummaryPageGenerator는 엄청나게 구체적입니다! 그리고 PrintUtility는 다시 일반화되고 있습니다.
따라서 시작하려면 클래스의 일반 이름을 피하고 대신 더 구체적인 이름을 사용해야합니다. 예를 들어, PrintUtility 클래스는 Header 클래스, Footer 클래스, TextBlock 클래스, Image 클래스를 포함하는 Print 클래스가 될 것이며 인쇄 자체에서 어떻게 흐르는 지 나타내는 방법 일 수도 있습니다. PrintUtility의 네임 스페이스 하지만.
데이터베이스의 경우 비슷한 이야기. 데이터베이스 액세스에 Entity Framework를 사용하더라도 사용하는 것으로 제한하고 논리 그룹으로 나누어야합니다.
그러나 4 년이 지난 후에도 여전히이 문제를 다루고 있는지 궁금합니다. 그렇다면 "절차 개념"에서 "객체 지향 개념"으로 바꿔야하는 사고 방식입니다. 경험이 없다면 어려울 것입니다 ...


-3

나는 내 의견이다, 당신은 간단하고 일관성 있고 읽기 쉬운 코드를 변경해야합니다.

이 주제에 대한 블로그 게시물을 작성했으며 이해하기 쉽다고 믿습니다. 좋은 코드 란 무엇입니까?

단순성 : 회로 기판에는 각기 다른 부품이 있으며 각 부품에는 책임이 있습니다. 코드는 더 작고 간단한 부분으로 나누어야합니다.

일관성 : 요소와 사물의 이름을 지정하는 표준 인 패턴을 사용하십시오. 당신은 항상 같은 방식으로 작동하는 도구를 좋아하고 어디에서 찾을 수 있는지 알고 싶어합니다. 코드와 동일합니다.

읽을 수있는 : 소프트웨어가 대상으로하는 도메인 (mattnz) 내에서 널리 사용되고 널리 사용되지 않는 한 두문자어를 사용하지 마십시오. 명확하고 이해하기 쉬운 이름을 선호합니다.


1
소프트웨어가 대상으로하는 도메인에서 널리 사용되고 널리 알려진 약어는 허용됩니다. 사용하지 않고 항공 교통 관제 소프트웨어를 작성해보십시오. 두문자어로 구성된 약어가 있습니다. 네트워킹을위한 HTTP, 자동차의 ABS 등은 완벽하게 허용됩니다.
mattnz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.