재사용 가능한 방법을 어떻게 알 수 있습니까? [닫은]


133

나는 집에서 내 자신의 사업을 생각하고 내 아내가 와서 말한다

여보 .. 2018 년 전 세계의 모든 Day Light Savings를 콘솔에서 인쇄 할 수 있습니까? 뭔가 확인해야합니다.

그리고 나는 그것이 Java 경험으로 평생 동안 기다리고 있었고 다음을 생각해 냈기 때문에 매우 행복합니다.

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(2018, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (2018 == now.getYear()) {
                    int hour = now.getHour();
                    now = now.plusHours(1);
                    if (now.getHour() == hour) {
                        System.out.println(now);
                    }
                }
            }
        );
    }
}

그러나 그녀는 그녀가 단지 나는 윤리적으로 훈련 된 소프트웨어 엔지니어가인지 저를 테스트했다라고, 내가부터 (에서 가져온 아니다 것 같습니다 하더군요 여기에 ) ..

윤리적으로 훈련 된 소프트웨어 엔지니어는 DestroyBaghdad 절차 작성에 동의하지 않습니다. 기본적인 전문 윤리는 그 대신 바그다드를 매개 변수로 제공 할 수있는 DestroyCity 절차를 작성해야합니다.

그리고 난 괜찮아, 알았어, 알았어 .. 당신이 원하는 해마다 지나 가세요 .

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings(int year) {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(year, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (year == now.getYear()) {
                    // rest is same..

그러나 매개 변수화 할 양 (및 무엇)을 어떻게 알 수 있습니까? 결국 그녀는 ..

  • 그녀는 사용자 정의 문자열 포맷터를 전달하려고합니다. 아마도 이미 인쇄중인 형식이 마음에 들지 않을 수 있습니다. 2018-10-28T02:00+01:00[Arctic/Longyearbyen]

void dayLightSavings(int year, DateTimeFormatter dtf)

  • 그녀는 특정 달에만 관심이 있습니다

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd)

  • 그녀는 특정 시간에 관심이 있습니다

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd, int hourStart, int hourend)

구체적인 질문을 찾고 있다면 :

경우 destroyCity(City city)보다 더 destroyBaghdad()있다 takeActionOnCity(Action action, City city)더 나은? 왜 왜 안돼?

결국, 내가 처음으로 호출 할 수 있습니다 Action.DESTROY다음 Action.REBUILD, 그렇지?

그러나 도시에 대한 조치를 취하는 것만으로는 충분하지 않습니다 takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea). 결국 나는 전화하고 싶지 않습니다.

takeActionOnCity(Action.DESTORY, City.BAGHDAD);

그때

takeActionOnCity(Action.DESTORY, City.ERBIL);

내가 할 수있을 때 등등 :

takeActionOnGeographicArea(Action.DESTORY, Country.IRAQ);

추신 : 나는 언급 한 인용문에 대해서만 내 질문을 세웠습니다. 세계의 모든 국가, 종교, 인종 또는 그 밖의 것에 반대하는 것은 없습니다. 난 그냥 지적하려고합니다.



71
여기서하는 요점은 여러 번 표현하려고 시도한 것입니다. 일반성은 비싸므로 구체적이고 명확한 이점으로 정당화되어야합니다 . 그러나 그것은 그것보다 더 깊다. 프로그래밍 언어는 디자이너가 다른 언어보다 일반성을 쉽게 만들도록 만들어져 개발자로서의 선택에 영향을줍니다. 메소드를 값 으로 쉽게 매개 변수화 할 수 있으며, 도구 상자에있는 가장 쉬운 도구 인 경우 사용자에게 적합한 지 여부에 관계없이 유혹을 사용합니다.
Eric Lippert

30
재사용은 자신이 원하는 것이 아닙니다. 코드 아티팩트는 비용이 많이 들고 가능한 많은 시나리오에서 사용할 수 있어야한다고 생각하기 때문에 재사용의 우선 순위를 정합니다. 이 신념은 종종 관찰에 의해 정당화되지 않으며, 따라서 재사용 성을위한 설계에 대한 조언은 종종 잘못 적용 됩니다. 응용 프로그램의 총 비용낮추기 위해 코드를 설계하십시오 .
Eric Lippert

7
당신의 아내는 당신에게 거짓말함으로써 시간을 낭비하는 비 윤리적 인 사람입니다. 그녀는 대답을 요청하고 제안 된 매체를 주었다. 그 계약에 의해, 당신이 그 결과를 얻는 방법은 오직 당신과 당신 사이에 있습니다. 또한 destroyCity(target)비 윤리적입니다 destroyBagdad()! 어떤 종류의 괴물이 세계의 어떤 도시는 물론 도시를 지우는 프로그램을 작성합니까? 시스템이 손상되면 어떻게됩니까?! 또한 시간 / 자원 관리 (투자 노력)는 윤리와 어떤 관련이 있습니까? 구두 / 서면 계약이 합의 된대로 완료되는 한.
Tezra

25
이 농담을 너무 많이 읽고있을 것 같아요. 컴퓨터 프로그래머가 자신의 작업이 인간에게 미치는 영향에 대한 기술적 고려 사항의 우선 순위를 정하기 때문에 나쁜 윤리적 결정을 내리는 방법에 대한 농담입니다. 프로그램 디자인에 대한 좋은 조언이 아닙니다.
Eric Lippert

답변:


114

거북은 끝까지 내려 왔습니다.

또는이 경우 추상화입니다.

모범 사례 코딩은 무한히 적용 할 수있는 것으로서, 추상화를 위해 추상화하는 중이므로 너무 많이 가져 왔습니다. 해당 라인을 찾는 것은 환경에 따라 크게 다르기 때문에 일반적으로 다루기가 쉽지 않습니다.

예를 들어, 간단한 응용 프로그램을 먼저 요청한 다음 확장을 요청하는 고객이있었습니다. 우리는 또한 고객이 원하는 것을 물어보고 일반적으로 확장을 위해 우리에게 다시 오지 않습니다.
귀하의 접근 방식은 고객마다 다릅니다. 첫 번째 고객의 경우 나중에이 코드를 다시 방문해야한다고 확신 할 수 있으므로 코드 를 사전에 추상적으로 지불 해야합니다. 두 번째 고객의 경우 어느 시점에서든 응용 프로그램을 확장하지 않으려는 경우 추가 노력을 기울이고 싶지 않을 수 있습니다 (참고 : 이는 모범 사례를 따르지 않고 단순히 현재 필요한 것 이상을 피 하십시오.

구현할 기능을 어떻게 알 수 있습니까?

내가 위에서 언급 한 이유는 이미이 함정에 빠졌기 때문입니다.

그러나 매개 변수화 할 양 (및 무엇)을 어떻게 알 수 있습니까? 결국, 그녀는 말할 수 있습니다 .

"그녀는 말할 수 있습니다"는 현재 비즈니스 요구 사항이 아닙니다. 미래의 비즈니스 요구 사항에 대한 추측입니다. 일반적으로 추측에 근거하지 말고 현재 필요한 것만 개발하십시오.

그러나 여기에 컨텍스트가 적용됩니다. 나는 당신의 아내를 모른다. 아마도 당신은 그녀가 실제로 이것을 원할 것이라고 정확하게 측정했을 것입니다. 그러나 고객 에게 이것이 실제로 원하는 것임을 계속 확인 해야합니다 .

어떤 아키텍처를 구현해야하는지 어떻게 알 수 있습니까?

더 까다 롭습니다. 고객은 내부 코드에 신경 쓰지 않으므로 필요한지 물어볼 수 없습니다. 이 문제에 대한 그들의 의견은 대부분 관련이 없습니다.

그러나 고객에게 올바른 질문 을 함으로써 여전히 그 필요성을 확인할 수 있습니다. 아키텍처에 대해 묻지 말고 향후 개발 또는 코드베이스 확장에 대한 기대치를 물어보십시오. 필요한 시간 내에 멋진 아키텍처를 구현하지 못할 수도 있으므로 현재 목표에 마감일이 있는지 물어볼 수도 있습니다.

코드를 더 추상화 할 때를 어떻게 알 수 있습니까?

나는 (누군가가 알고 있다면 저에게 알려 주시면 신용을주지)을 읽을 어디 모르겠지만, 엄지 손가락의 좋은 규칙은 개발자가 원시인처럼 계산해야한다는 것입니다 : 하나, 둘 많은 .

여기에 이미지 설명을 입력하십시오 XKCD # 764

즉, 특정 알고리즘 / 패턴을 세 번째 로 사용 하는 경우 재사용 가능하도록 (= 여러 번 사용할 수 있도록) 추상화해야합니다 .

분명히 말해서, 사용중인 알고리즘의 인스턴스가 두 개일 때 재사용 가능한 코드를 작성해서는 안된다는 것을 암시하지 않습니다. 물론이를 추상화 할 수도 있지만 세 가지 경우에 대해 추상화 해야합니다 .

다시, 이것은 당신의 기대에 영향을 미칩니다. 세 개 이상의 인스턴스가 필요하다는 것을 이미 알고 있다면, 즉시 추상화 할 수 있습니다. 그러나 더 많은 시간을 구현하고 싶을 것이라고 추측 하는 경우 추상화 구현의 정확성은 추측의 정확성에 전적으로 달려 있습니다.
올바르게 추측하면 시간을 절약 할 수 있습니다. 잘못 추측하면 시간과 노력을 낭비하고 필요하지 않은 결과를 구현하기 위해 아키텍처를 손상시킬 수 있습니다.

경우 destroyCity(City city)보다 더 destroyBaghdad()있다 takeActionOnCity(Action action, City city)더 나은? 왜 왜 안돼?

그것은 여러 가지에 달려 있습니다.

  • 어느 도시 에서든 여러 가지 조치를 취할 수 있습니까?
  • 이러한 동작을 서로 바꿔 사용할 수 있습니까? "파괴"및 "재 빌드"조치의 실행이 완전히 다른 경우 두 takeActionOnCity메소드를 단일 메소드 로 병합 할 필요가 없습니다 .

또한 이것을 재귀 적으로 추상화하면 다른 방법을 실행할 수있는 컨테이너에 지나지 않는 추상적 인 방법으로 끝날 것입니다.
전체 takeActionOnCity(Action action, City city)분석법 본문이 그 이상으로 끝나지 action.TakeOn(city);않는다면 takeActionOnCity분석법에 실제로 목적이 있거나 가치가없는 추가 레이어가 아닌지 궁금해야 합니다.

그러나 도시에 대한 조치를 취하는 것만으로는 충분하지 않습니다 takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea).

같은 질문이 여기에 나타납니다.

  • 지역에 대한 사용 사례가 있습니까?
  • 도시와 지역에 대한 조치의 실행이 동일합니까?
  • 어느 지역이나 도시에서도 어떤 조치를 취할 수 있습니까?

세 가지 모두에 "예"라고 확실히 대답 할 수 있으면 추상화가 필요합니다.


16
나는 "하나, 둘, 많은"규칙을 충분히 강조 할 수 없습니다. 무언가를 추상화 / 매개 변수화 할 수있는 무한한 가능성이 있지만 유용한 부분 집합은 작고 종종 0입니다. 어떤 변형이 가치가 있는지 정확히 아는 것은 대부분의 경우에만 소급해서 만 결정될 수 있습니다. 따라서 즉각적인 요구 사항 *을 고수하고 새로운 요구 사항이나 후시 사항에 따라 복잡성을 추가하십시오. * 때때로 문제의 공간을 잘 알고 있다면, 내일 필요하다는 것을 알기 때문에 무언가를 추가하는 것이 좋습니다. 그러나이 힘을 지혜롭게 사용하면 파멸로 이어질 수도 있습니다.
Christian Sauer

2
> "어디에서 읽었는지 모르겠습니다 [..]". 코딩 공포 : 3의 법칙을 읽었을 것 입니다.

10
"하나, 둘, 많은 규칙"은 DRY를 맹목적으로 적용하여 잘못된 추상화를 만드는 것을 방지하기 위해 실제로 존재합니다. 문제는 두 조각의 코드가 거의 똑같이 보이기 시작할 수 있기 때문에 차이점을 추상화하려는 유혹입니다. 그러나 초기에는 코드의 어느 부분이 안정적인지, 어떤 부분이 안정적인지 알 수 없습니다. 게다가, 그들은 실제로 독립적으로 진화해야한다는 것을 알 수있었습니다 (다른 변화 패턴, 다른 책임 세트). 두 경우 모두 잘못된 추상화가 사용자에게 불리하게 작용하여 방해가됩니다.
Filip Milovanović

4
"동일한 논리"에 대한 두 개 이상의 예를 기다리면 추상화해야 할 사항과 방법 (및 실제로 변경 패턴이 다른 코드 간 종속성 관리 / 커플 링에 대한)을 더 잘 판단 할 수 있습니다.
Filip Milovanović

1
@ kukis : Baldrickk의 의견에 따라 현실적인 선은 2로 그려야합니다 : 데이터베이스 관계의 경우와 마찬가지로 0 대 1입니다. 그러나 이것은 불필요한 패턴 추구 행동의 문을 열어줍니다. 두 가지가 모호하게 보일 수 있지만 이것이 실제로 동일하다는 것을 의미하지는 않습니다. 그러나 세 번째 인스턴스가 첫 번째 인스턴스와 두 번째 인스턴스 모두와 유사한 방식으로 시작되면 유사성이 실제로 재사용 가능한 패턴인지 더 정확하게 판단 할 수 있습니다. 따라서 상식선은 3으로 그려지며, 두 인스턴스 사이에서 "패턴"을 발견 할 때 인적 오류가 발생합니다.
Flater

44

연습

이것은 소프트웨어 엔지니어링 SE이지만 소프트웨어 제작은 엔지니어링보다 훨씬 예술적입니다. 재사용 성이 얼마나 충분한 지 파악하기 위해 따라야 할 보편적 인 알고리즘이나 측정법은 없습니다. 다른 프로그램과 마찬가지로 프로그램을 더 많이 연습할수록 더 잘 배울 수 있습니다. 매개 변수를 너무 많거나 적을 때 무엇이 ​​잘못되었는지, 어떻게 잘못되는지 알 수 있기 때문에 "충분한"것이 무엇인지 더 잘 느낄 수 있습니다.

그래도 지금은 별로 도움이되지 않으므로 몇 가지 지침은 어떻습니까?

질문을 다시보십시오. "그녀가 말할 수도있다"와 "나는 할 수있다"가 많이 있습니다. 미래의 필요에 대해 이론화하는 많은 진술. 인간은 미래를 예측할 수 있습니다. 그리고 당신은 (아마도) 인간입니다. 소프트웨어 디자인의 압도적 인 문제는 당신이 모르는 미래를 설명하려고합니다.

지침 1 : 당신은 그것을 필요로하지 않습니다

진심으로. 그냥 멈춰. 그보다 더 자주, 그 미래의 문제는 나타나지 않습니다-그리고 당신이 상상했던 것처럼 나타나지 않을 것입니다.

지침 2 : 비용 / 혜택

멋지다, 그 작은 프로그램은 몇 시간 동안 글을 쓸까? 아내 돌아와서 그런 것들을 구하면 어떻게 될까요? 최악의 경우, 다른 프로그램을 함께 던지기 위해 몇 시간을 더 보냅니다. 이 경우이 프로그램을보다 융통성있게 만드는 데 너무 많은 시간이 걸리지 않습니다. 그리고 런타임 속도 나 메모리 사용량을 크게 늘리지 않을 것입니다. 그러나 사소하지 않은 프로그램에는 다른 답변이 있습니다. 시나리오마다 답변이 다릅니다. 언젠가는, 불완전한 미래의 말하기 능력이 있어도 비용은 분명히 가치가 없습니다.

지침 3 : 상수에 초점

질문을 다시보십시오. 원래 코드에는 많은 상수가 있습니다. 2018, 1. 상수 int, 상수 문자열 ... 상수가 아닌 것이 가장 필요할 것 입니다. 더 좋은 점은 매개 변수화 (또는 실제 상수로 정의하는 데)에 약간의 시간이 걸립니다. 그러나 조심해야 할 또 다른 것은 지속적인 행동 입니다. 그만큼System.out.println예를 들어. 이러한 사용에 대한 가정은 미래에 변화하는 경향이 있으며 고치는 데 비용이 많이 드는 경향이 있습니다. 뿐만 아니라 이와 같은 IO는 시간대를 약간 가져 오는 것과 함께 함수를 불완전하게 만듭니다. 해당 동작을 매개 변수화하면 기능을보다 순수하게하여 유연성과 테스트 가능성을 높일 수 있습니다. 최소한의 비용으로 큰 이점 (특히 System.out기본적으로 사용 되는 과부하를 만드는 경우 ).


1
그것은 단지 지침 일뿐입니다. 1은 괜찮지 만 당신은 그것들을보고“이것이 변할 것입니까?” println은 고차 함수로 매개 변수화 될 수 있습니다 .Java는 그다지 훌륭하지 않습니다.
Telastyn

5
@ KorayTugay : 프로그램이 실제로 집에 오는 아내를위한 것이라면 YAGNI는 초기 버전이 완벽하다고 말하며 상수 또는 매개 변수를 도입하기 위해 더 이상 시간을 투자해서는 안됩니다. YAGNI는 맥락 이 필요 합니다. 프로그램이 폐기 솔루션입니까, 마이그레이션 프로그램이 몇 개월 동안 만 실행됩니까, 아니면 수십 년 동안 사용 및 유지 관리하기위한 거대한 ERP 시스템의 일부입니까?
Doc Brown

8
@KorayTugay : I / O를 계산에서 분리하는 것은 기본적인 프로그램 구조화 기술입니다. 데이터 표현으로부터 데이터 소비로부터의 데이터 변환으로부터의 데이터 필터링으로부터 데이터의 생성을 분리한다. 일부 기능성 프로그램을 공부하면 더 명확하게 볼 수 있습니다. 함수형 프로그래밍에서는 무한한 양의 데이터를 생성하고, 원하는 데이터 만 필터링하고, 필요한 형식으로 데이터를 변환하고, 문자열을 구성하고,이 문자열을 5 가지 기능으로 인쇄하는 것이 일반적입니다. 각 단계마다 하나씩.
Jörg W Mittag

3
부수적으로, YAGNI를 강력하게 따르는 것은 지속적으로 리팩토링을 계속해야 할 필요가 있습니다. 따라서 YAGNI는 일반적으로 좋은 일이지만 코드를 다시 검토하고 재평가해야 할 큰 책임이 있습니다. 이는 모든 개발자 / 회사가 기꺼이 할 일이 아닙니다.
Flater

4
@Telastyn : 나는“이것은 절대 변하지 않을 것이며 상수를 명명하지 않고 사소하게 읽을 수있는 코드의 의도 입니까?” 라는 질문을 확장 할 것을 제안 합니다.
Flater

27

첫째 : 보안을 염두에 둔 소프트웨어 개발자는 어떠한 이유로 든 인증 토큰을 전달하지 않고 DestroyCity 메서드를 작성하지 않습니다.

나도 다른 맥락에서 적용 할 수없는 명백한 지혜가있는 명령으로 쓸 수있다. 문자열 연결을 승인해야하는 이유는 무엇입니까?

둘째 : 실행될 때 모든 코드를 완전히 지정해야합니다 .

결정이 하드 코딩되어 있거나 다른 계층으로 연기되었는지 여부는 중요하지 않습니다. 어느 시점에는 어떤 언어로 코드를 파괴해야하는지, 어떻게 지시 하는지를 아는 코드가 있습니다.

동일한 객체 파일 destroyCity(xyz)에있을 수도 있고 구성 파일에 destroy {"city": "XYZ"}"있을 수도 있습니다 : 또는 UI에서 일련의 클릭 및 키 누르기 일 수 있습니다.

셋째 :

여보 .. 2018 년 전 세계의 모든 Day Light Savings를 콘솔에서 인쇄 할 수 있습니까? 뭔가 확인해야합니다.

다음과 같은 요구 사항이 매우 다릅니다.

그녀는 사용자 지정 문자열 포맷터를 전달하려고합니다. 특정 월 기간에만 관심이 있고 특정 시간 기간에 관심이 있습니다.

이제 두 번째 요구 사항은보다 유연한 도구를 만듭니다. 광범위한 대상과 응용 범위가 넓습니다. 여기서 가장 위험한 것은 세계에서 가장 유연한 응용 프로그램은 실제로 기계 코드의 컴파일러라는 것입니다. 문자 그대로 프로그램이므로 컴퓨터의 하드웨어 제약 조건 내에서 컴퓨터를 원하는대로 만들 수있는 모든 것을 만들 수 있습니다.

일반적으로 소프트웨어가 필요한 사람들은 일반적인 것을 원하지 않습니다. 그들은 특정한 것을 원합니다. 더 많은 옵션을 제공함으로써 당신은 실제로 그들의 삶을 더 복잡하게 만듭니다. 그들이 그 복잡성을 원한다면, 대신 묻지 않고 컴파일러를 사용하고있을 것입니다.

당신의 아내는 기능을 요구하고 있었고, 그녀에게 당신의 요구 사항을 과소 평가했습니다. 이 경우에는 의도적으로 보였으며 일반적으로 더 잘 알지 못하기 때문입니다. 그렇지 않으면 방금 컴파일러 자체를 사용했을 것입니다. 첫 번째 문제는 그녀가하고 싶은 일에 대한 자세한 내용을 요구하지 않았다는 것입니다. 그녀는 몇 년 동안 이것을 실행하고 싶었습니까? CSV 파일로 원했습니까? 당신은 그녀가 어떤 결정을 내릴 것인지, 그리고 그녀가 무엇을 알아 내고 결정할 것인지를 찾지 못했습니다. 어떤 결정을 연기해야하는지 파악한 후에는 매개 변수 (및 기타 구성 가능한 수단)를 통해 이러한 결정을 전달하는 방법을 알아낼 수 있습니다.

다시 말해서, 대부분의 고객은 의사 소통을하거나 의사 소통을하거나 의사 소통을하거나 자신이 실제로하고 싶어하거나 실제로하고 싶지 않은 특정 세부 사항 (일명 의사 결정)을 모르고 있습니다. PDSA (plan-develop-study-act) 와 같은 작업 방법 이 중요한 이유 입니다. 요구 사항에 따라 작업을 계획 한 다음 일련의 결정 (코드)을 개발했습니다. 이제 스스로 또는 고객과 함께 공부하고 새로운 것을 배우고, 앞으로 생각을 알려줄 때입니다. 마지막으로 새로운 통찰력을 활용하여 요구 사항을 업데이트하고 프로세스를 수정하고 새로운 도구를 구하십시오. 그런 다음 다시 계획을 시작하십시오. 이것은 시간이 지남에 따라 숨겨진 요구 사항을 보여 주며 많은 고객에게 진전을 보여줍니다.

드디어. 당신의 시간이 중요합니다 ; 그것은 매우 현실적이고 유한합니다. 모든 의사 결정에는 다른 많은 숨겨진 의사 결정이 수반되며 이는 소프트웨어 개발에 관한 것입니다. 결정을 인수로 지연하면 현재 기능이 더 단순 해지지 만 다른 곳에서는 더 복잡해집니다. 그 결정이 다른 지역과 관련이 있습니까? 더 관련이 있습니까? 실제로 누구의 결정을 내립니까? 당신은 이것을 결정하고 있습니다; 이것은 코딩입니다. 결정 집합을 자주 반복하면 일부 추상화 내부에서 결정을 체계화 할 때 매우 큰 이점이 있습니다. XKCD 는 여기서 유용한 관점을 가지고 있습니다. 그리고 이것은 기능, 모듈, 프로그램 등 시스템 수준에서 관련이 있습니다.

처음에 조언은 당신의 기능이 할 권리가없는 결정이 논쟁으로 전달되어야 함을 의미합니다. 문제는 DestroyBaghdad함수가 실제로 그 권한 을 가진 함수일 수 있다는 것입니다.


+1은 컴파일러에 대한 부분을 좋아합니다!
Lee

4

여기에 긴 답변이 많이 있지만 솔직히 말하면 매우 간단합니다.

함수에서 함수 이름에 속하지 않은 하드 코딩 된 정보는 매개 변수 여야합니다.

그래서 당신의 기능에서

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(zoneId -> {
            LocalDateTime dateTime = LocalDateTime.of(LocalDate.of(2018, 1, 1), LocalTime.of(0, 0, 0));
            ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
            while (2018 == now.getYear()) {
                int hour = now.getHour();
                now = now.plusHours(1);
                if (now.getHour() == hour) {
                    System.out.println(now);
                }
            }
        });
    }
}

당신은 :

The zoneIds
2018, 1, 1
System.out

그래서이 모든 것을 하나의 형태로 매개 변수로 옮길 것입니다. zoneIds가 함수 이름에 내재되어 있다고 주장 할 수 있습니다. "DaylightSavingsAroundTheWorld"또는 다른 것으로 변경하여 더 만들려고 할 수 있습니다.

형식 문자열이 없으므로 기능 문자열을 추가하는 것은 기능 요청이므로 아내를 가족 Jira 인스턴스에 문의해야합니다. 백 로그에 기록하고 적절한 프로젝트 관리위원회 회의에서 우선 순위를 지정할 수 있습니다.


1
당신은 (내 자신을 OP로 주소 지정) 아무것도 인쇄하지 않아야하기 때문에 형식 문자열을 추가해서는 안됩니다. 이 코드에서 재사용을 절대적으로 방지하는 한 가지는 인쇄하는 것입니다. DST를 떠났을 때 영역 또는 영역 맵을 반환해야합니다. (그것은 단지 식별 왜 때 이동하지만 오프 DST, 그리고를 DST, 이해가 안 문제 설명과 일치하지 않는 것 같습니다..)
데이비드 콘래드에게

요구 사항은 콘솔에 인쇄하는 것입니다. 내가 제안한대로 출력 스트림을 매개 변수로 전달하여 꽉 찬 쿠 플런을 완화 할 수 있습니다.
Ewan

1
그럼에도 불구하고 코드를 재사용 할 수있게하려면 콘솔에 인쇄하지 않아야합니다. 결과를 반환하는 메서드를 작성한 다음 결과를 가져 와서 인쇄하는 호출자를 작성하십시오. 또한 테스트 가능합니다. 출력을 생성하려면 출력 스트림을 전달하지 않고 소비자를 전달합니다.
David Conrad

ourput 스트림은 소비자입니다
Ewan

아니요, OutputStream소비자 가 아닙니다 .
David Conrad

4

즉, 최종 사용자가 기능을 재사용 할 수 있는지 신경 쓰지 않기 때문에 재사용 성을 위해 소프트웨어를 엔지니어링하지 마십시오. 대신, 설계 이해를 위한 엔지니어 -다른 사람이나 미래의 잊어 버린 자아가 이해하기 쉬운 코드입니까? - 설계 유연성필연적으로 버그를 수정하거나, 기능을 추가하거나, 기능을 수정해야 할 때 내 코드가 변경 사항에 얼마나 영향을 줍니까? 고객이 관심을 갖는 유일한 것은 버그를보고하거나 변경을 요청할 때 얼마나 빨리 응답 할 수 있는지입니다. 우연히 디자인에 대한 이러한 질문을하면 재사용 가능한 코드가 생성되는 경향이 있지만,이 접근 방식을 통해 코드 수명 동안 직면 할 실제 문제를 피하는 데 집중할 수 있으므로, 엄격하고 실용적이지 않고 최종 사용자에게 더 나은 서비스를 제공 할 수 있습니다. 목 수염을 기쁘게하는 "엔지니어링"이상.

제공 한 예제만큼 단순한 것은 초기 구현은 크기가 작기 때문에 훌륭하지만, 이처럼 단순한 디자인은 너무 많은 기능적 유연성 (설계 유연성이 아닌)을 방해하면 이해하기 어렵고 부서지기 쉽습니다. 하나의 절차. 아래는 이해와 유연성을 위해 복잡한 시스템을 설계하는 데 선호되는 접근 방식에 대한 설명입니다. 이 절차는 단일 절차에서 20 줄 미만으로 쓰여질 수있는 것에 대해서는 사용하지 않을 것입니다. 왜냐하면 아주 작은 것이 이미 이해력과 유연성에 대한 나의 기준을 충족시키기 때문입니다.


절차가 아닌 객체

구식 모듈과 같은 클래스를 사용하여 소프트웨어가 수행해야하는 작업을 실행하기 위해 호출하는 많은 루틴을 사용하는 대신, 작업을 수행하기 위해 상호 작용하고 협력하는 객체로 도메인을 모델링하는 것을 고려하십시오. 객체 지향 패러다임의 메소드는 원래 그 때문에 객체 사이의 신호로 만들어진 Object1말할 수있는 Object2그 무엇이든 그 일을 수행하고, 아마도 리턴 신호를받을 수 있습니다. 이는 객체 지향 패러다임이 본질적으로 명령형 패러다임의 동일한 기존 기능과 절차를 구성하는 멋진 방법이 아니라 도메인 객체와 해당 상호 작용을 모델링하는 것이기 때문입니다. 의 경우void destroyBaghdad예를 들어, 바그다드 나 다른 것들 (빠르게 복잡하고 이해하기 어렵고 부서지기 쉬운)의 파괴를 처리하기 위해 문맥이없는 일반적인 방법을 쓰려고 노력하는 대신, 파괴 될 수있는 모든 것은 방법을 이해해야합니다. 스스로를 파괴합니다. 예를 들어, 파괴 할 수있는 것들의 동작을 설명하는 인터페이스가 있습니다.

interface Destroyable {
    void destroy();
}

그런 다음이 인터페이스를 구현하는 도시가 있습니다.

class City implements Destroyable {
    @Override
    public void destroy() {
        ...code that destroys the city
    }
}

인스턴스의 파괴를 요구 City하는 것은 그 일이 어떻게 발생하는지 신경 쓰지 않을 것이므로 코드가 외부 어디에도 존재할 이유가 없으며 City::destroy실제로 City외부 외부의 내부 작업에 대한 친밀한 지식은 긴밀한 결합으로 감소합니다. 의 동작을 수정해야하는 경우 외부 요소를 고려해야하기 때문에 실현 가능성 City. 이것이 캡슐화의 진정한 목적입니다. 모든 객체에는 자체 API가 있으므로 필요한 모든 작업을 수행하여 요청 이행에 대해 걱정할 수 있도록해야합니다.

"제어"가 아닌 위임

지금, 당신의 구현 클래스인지 City또는 Baghdad도시를 파괴하는 과정이 밝혀 방법 일반에 따라 달라집니다. 모든 가능성에서, City도시는 도시의 완전한 파괴를 달성하기 위해 개별적으로 파괴 될 필요가있는 더 작은 조각들로 구성 될 것이고,이 경우, 이들 조각들 각각은 또한 구현 될 것이고 Destroyable, 그들은 각각 City파괴 하도록 지시 될 것이다. 같은 방식으로 외부에서 누군가가 City자신을 파괴 하도록 요청했습니다 .

interface Part extends Destroyable {
    ...part-specific methods
}

class Building implements Part {
    ...part-specific methods
    @Override
    public void destroy() {
       ...code to destroy a building
    }
}

class Street implements Part {
    ...part-specific methods
    @Override
    public void destroy() {
        ...code to destroy a building
    }
}

class City implements Destroyable {
    public List<Part> parts() {...}

    @Override
    public void destroy() {
        parts().forEach(Destroyable::destroy);            
    }
}

정말 미치게 만들고 Bomb특정 위치에 놓이고 특정 반경 내의 모든 것을 파괴 하는 아이디어를 구현하려는 경우 다음과 같이 보일 수 있습니다.

class Bomb {
    private final Integer radius;

    public Bomb(final Integer radius) {
        this.radius = radius;
    }

    public void drop(final Grid grid, final Coordinate target) {
        new ObjectsByRadius(
            grid,
            target,
            this.radius
        ).forEach(Destroyable::destroy);
    }
}

ObjectsByRadiusBomb입력에 대해 계산되는 개체 집합을 나타내며 개체에 대해 Bomb작업 할 수있는 한 계산 방법을 신경 쓰지 않기 때문 입니다. 이것은 우연히 재사용 가능하지만 주요 목표는 Bomb객체 를 떨어 뜨리고 파괴 하는 프로세스에서 계산을 분리하여 각 조각을 이해하고 전체 알고리즘을 재구성하지 않고도 개별 조각의 동작을 변경하고 개별 조각의 동작을 변경하는 것입니다. .

알고리즘이 아닌 상호 작용

복잡한 알고리즘에 대해 적절한 수의 매개 변수를 추측하는 대신 프로세스를 복잡한 역할을하는 일련의 상호 작용 객체로 모델링하는 것이 더 합리적입니다. 잘 정의되고 이해하기 쉽고 거의 변하지 않는 객체 간의 상호 작용을 통해 프로세스를 수행합니다. 올바르게 수행하면 인터페이스를 구현하거나 main()메소드 에서 인스턴스화 된 객체를 재 작업하는 것처럼 사소한 수정처럼 가장 복잡한 수정도 가능합니다 .

나는 당신에게 당신의 원래 예제에 무언가를 줄 것이지만, 솔직히 "인쇄 ​​... Day Light Savings"라는 것이 무엇을 의미하는지 이해할 수 없습니다. 그 범주의 문제에 대해 말할 수있는 것은 계산을 수행 할 때마다 여러 가지 형식으로 결과를 형식화 할 수 있다는 것입니다.

interface Result {
    String print();
}

class Caclulation {
    private final Parameter paramater1;

    private final Parameter parameter2;

    public Calculation(final Parameter parameter1, final Parameter parameter2) {
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
    }

    public Result calculate() {
        ...calculate the result
    }
}

class FormattedResult {
    private final Result result;

    public FormattedResult(final Result result) {
        this.result = result;
    }

    @Override
    public String print() {
        ...interact with this.result to format it and return the formatted String
    }
}

이 예제에서는이 디자인을 지원하지 않는 Java 라이브러리의 클래스를 사용하므로 ZonedDateTime직접 API를 사용할 수 있습니다. 여기서의 아이디어는 각 계산이 자체 객체 내에 캡슐화된다는 것입니다. 실행 횟수 나 결과 형식화 방법에 대해서는 가정하지 않습니다. 가장 간단한 형태의 계산 수행에만 관심이 있습니다. 따라서 이해하기 쉽고 유연하게 변경할 수 있습니다. 마찬가지로,는 Result계산 결과를 캡슐화하는 FormattedResult것과 관련이 있으며, Result정의한 규칙에 따라 형식을 지정하기 위해 와 상호 작용하는 것만 관련됩니다. 이런 식으로,우리는 각각의 메소드가 잘 정의 된 작업을 가지고 있기 때문에 각 메소드에 대해 완벽한 인수를 찾을 수 있습니다 . 또한 인터페이스가 변경되지 않는 한 (객체의 책임을 올바르게 최소화 한 경우에는 수행 할 수없는) 앞으로 수정하는 것이 훨씬 간단합니다. 우리의main()방법은 다음과 같습니다.

class App {
    public static void main(String[] args) {
        final List<Set<Paramater>> parameters = ...instantiated from args
        parameters.forEach(set -> {
            System.out.println(
                new FormattedResult(
                    new Calculation(
                        set.get(0),
                        set.get(1)
                    ).calculate()
                ).print()
            );
        });
    }
}

실제로 객체 지향 프로그래밍은 명령 방식의 복잡성 / 유연성 문제에 대한 해결책으로 특별히 고안되었습니다. 관용구 내에 명령 기능 및 절차를 지정하십시오.


이것은 매우 상세하고 신중한 답변이지만 불행히도 OP가 실제로 요구 한 것에 대한 표시를 놓친 것 같습니다. 그는 그의 훌륭한 예를 해결하기 위해 좋은 OOP 관행에 대한 교훈을 요구하지 않았으며, 솔루션 대 일반화에 시간 투자를 결정하는 기준에 대해 묻고있었습니다.
maple_shaft

@maple_shaft 어쩌면 내가 마크를 놓쳤을 수도 있지만, 당신도 가지고 있다고 생각합니다. OP는 시간 투자 대 일반화에 대해 묻지 않습니다. "내 방법이 얼마나 재사용 가능한지 어떻게 알 수 있습니까?" 그는 자신의 질문을 계속해서 묻습니다. "destroyCity (City city)가 destroyBaghdad ()보다 낫다면 takeActionOnCity (Action action, City city)가 더 나을까요? 왜 / 왜 안 되나요?" 엔지니어링 솔루션에 대한 대안적인 접근 방법을 제시하여 방법을 만드는 일반적인 방법을 찾는 문제를 해결하고 내 주장을 뒷받침하는 예를 제공했습니다. 마음에 들지 않아서 죄송합니다.
Stuporman

@maple_shaft 솔직히 말해서, 우리의 나머지는 그의 의도에 대한 우리의 해석을 방어하는 전쟁에서 싸울 수 있기 때문에 내 대답이 그의 질문과 관련이 있는지의 여부 만 OP가 결정할 수 있습니다.
Stuporman

@maple_shaft 질문과의 관련성을 명확히하기 위해 소개를 추가하고 답변과 예제 구현 사이에 명확한 설명을 제공했습니다. 더 낫습니까?
Stuporman

1
솔직히 이러한 원칙을 모두 적용하면 대답은 자연스럽고 매끄럽고 읽기 쉽습니다. 또한 많은 번거 로움없이 변경 가능합니다. 나는 당신이 누군지 모르지만 더 많은 사람이 있기를 바랍니다! 괜찮은 OO에 대한 반응성 코드를 계속 리핑하고 크기는 항상 절반이며 더 읽기 쉽고 제어 가능하며 스레딩 / 분할 / 매핑이 있습니다. React는 방금 나열된 "기본"개념을 이해하지 못하는 사람들을위한 것이라고 생각합니다.
Stephen J

3

경험 , 도메인 지식코드 검토.

또한 경험 , 도메인 지식 또는 팀의 규모와 관계없이 필요에 따라 리팩터링 할 필요가 없습니다.


Experience를 사용하면 작성 하는 도메인 비 특정 메소드 (및 클래스)에서 패턴을 인식하기 시작합니다. 그리고 DRY 코드에 관심이 있다면 , 미래에 변형을 쓸 것이라는 것을 본능적으로 알고 있는 메소드를 작성할 때 기분이 나빠질 것입니다. 따라서 매개 변수화 된 최소 공통 분모를 직관적으로 작성할 수 있습니다 .

(이 경험은 일부 도메인 객체 및 메소드로 본능적으로 전환 될 수 있습니다.)

Domain Knowledge를 사용하면 비즈니스 개념이 밀접하게 관련되어 있고, 어떤 개념에 변수가 있고, 정적 인 등의 개념이 있습니다.

Code Review를 사용하면 프로덕션 코드가되기 전에 매개 변수 부족 및 초과 매개 변수화가 발생할 가능성이 높습니다. 동료는 일반적으로 도메인코딩에 대해 고유 한 경험과 관점을 갖기를 바랍니다 .


즉, 새로운 개발자에게는 일반적으로 이러한 Spidey Sense 또는 경험이 풍부한 동료 그룹이 즉시 기댈 필요가 없습니다. 또한 숙련 된 개발자 조차도 새로운 요구 사항 또는 뇌가 낀 날을 통해 기본 지침을 통해 지침을 얻을 수 있습니다. 여기 에 시작으로 제안 하는 것이 있습니다 .

  • 최소한의 매개 변수로 순진한 구현으로 시작하십시오.
    ( 필요하다고 이미 알고 있는 매개 변수를 모두 포함하십시오 .)
  • 마법의 숫자와 문자열을 제거하여 구성 및 / 또는 매개 변수로 이동
  • "큰"방법을 더 작고 잘 알려진 방법으로 분해
  • 중복성이 높은 방법 (편리한 경우)을 공통 분모로 리팩토링하여 차이를 매개 변수화합니다.

이러한 단계가 반드시 명시된 순서대로 발생하는 것은 아닙니다. 이미 기존 방법과 중복성이 높은 방법을 작성하기 위해 앉아있는 경우 편리한 경우 리팩토링으로 바로 넘어갑니다 . 리팩토링하는 데 시간이 많이 걸리지 않으면 두 가지 방법을 작성, 테스트 및 유지 관리하는 것보다 훨씬 많은 시간이 소요됩니다.

그러나 경험이 많지 않은 것 외에도 최소한의 코드 DRY-ing을 권합니다. 명백한 위반을 리팩토링하는 것은 어렵지 않습니다. 또한 너무 열성적인 경우 "WET"에 비해 읽기, 이해 및 유지 관리가 훨씬 어려운 "과도하게 건조 된"코드로 끝날 수 있습니다.


2
따라서 정답은 없습니다 If destoryCity(City city) is better than destoryBaghdad(), is takeActionOnCity(Action action, City city) even better?? 예 / 아니오 질문이지만 답변이 없습니다. 또는 초기 가정이 틀렸을 destroyCity(City)수도 있고, 더 나을 필요는 없으며 실제로 달려 있습니까? 그렇다고해서 매개 변수없이 직접 구현했기 때문에 윤리적으로 훈련 된 소프트웨어 엔지니어 가 아니라는 의미는 아닙니다 . 내가 묻는 구체적인 질문에 대한 답은 무엇입니까?
Koray Tugay

당신의 질문은 몇 가지 질문을합니다. 제목 질문에 대한 대답은 "경험, 도메인 지식, 코드 검토 ... 및 ... 리팩토링을 두려워하지 마십시오."입니다. 구체적인 방법에 대한 대답은 "방법 ABC에 대한 올바른 매개 변수입니까?"라는 질문입니다. "모르겠습니다. 왜 묻습니까? 현재 가지고있는 매개 변수의 수에 문제가 있습니까 ??? 그렇다면 해결하십시오. " ... 추가 지침 을 위해 "POAP" 를 참조 할 수 있습니다 . 왜하고있는 일을하고 있는지 이해해야합니다!
svidgen

내 말은 ... destroyBaghdad()방법 에서 한 걸음 물러서 자 . 문맥이 무엇입니까? 바그다드가 게임을 끝내면 파괴되는 비디오 게임입니까 ??? 그렇다면 ... destroyBaghdad()완벽하게 합리적인 분석법 이름 / 서명일 수 있습니다 ...
svidgen

1
그래서 당신은 내 질문에 인용 된 인용문에 동의하지 않습니다. It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure.당신이 Nathaniel Borenstein과 함께 방에 있었다면, 당신은 그에게 그것이 실제로 달려 있고 그의 진술이 정확하지 않다고 주장 할 것 입니까? 많은 사람들이 응답하고 시간과 에너지를 소비하는 것이 아름답다는 것을 의미합니다. 그러나 어디에서나 하나의 구체적인 대답을 볼 수는 없습니다. Spidey-senses, code review .. 그러나 그 답은 is takeActionOnCity(Action action, City city) better? null무엇입니까?
Koray Tugay

1
@svidgen 물론 추가적인 노력없이 이것을 추상화하는 또 다른 방법은 의존성을 뒤집는 것입니다-함수가 도시에 대한 조치를 수행하는 대신 도시 목록을 반환하도록하는 것입니다 (원래 코드의 "println"). 이것은 필요할 경우 더 추상화 될 수 있지만,이 하나의 변경만으로도 원래 질문에 추가 된 요구 사항의 약 절반을 처리 할 수 ​​있습니다. 모든 종류의 나쁜 일을 수행 할 수있는 하나의 불순한 함수 대신 목록을 반환하고 호출자 는 나쁜 일을합니다.
Luaan

2

품질, 유용성, 기술 부채 등과 동일한 답변 :

등의 재사용으로 하면, 사용자, 1 로 그들을 필요

추상화를 설계하고 유지하는 비용이 비용 (= 시간과 노력)에 의해 상환 될 것인지의 여부는 기본적으로 판단 요구입니다.

  • "다운 라인"이라는 문구에 주목하십시오. 여기에는 지불 방식이 있습니다. 따라서이 코드로 얼마나 더 작업 할 것인지에 따라 달라집니다. 예 :
    • 이것은 일회성 프로젝트입니까, 아니면 장기간에 걸쳐 점진적으로 개선 될 것입니까?
    • 디자인에 확신이 있습니까? 아니면 다음 프로젝트 / 마일스톤을 위해 디자인을 폐기하거나 다른 방식으로 대폭 변경해야합니까 (예 : 다른 프레임 워크 시도)?
  • 예상 이익은 또한 미래 예측 능력 (앱 변경)에 달려 있습니다. 때로는 앱이 열릴 장소를 합리적으로 볼 수 있습니다. 더 많은 시간, 당신은 당신이 할 수 있다고 생각하지만 실제로는 할 수 없습니다. 여기에서 경험할 규칙은 YAGNI 원칙세 가지 규칙입니다. 둘 다 지금 아는 것에서 벗어나는 것을 강조 합니다.

1 이것은 코드 구조이므로이 경우 "사용자"입니다. 소스 코드의 사용자


1

따라야 할 명확한 과정이 있습니다.

  • 그 자체가 "사물"인 단일 기능에 대해 실패한 테스트를 작성하십시오 (즉, 절반이 실제로 의미가없는 기능의 임의 분할은 아님).
  • 절대 최소 코드를 작성하여 줄이 아니라 녹색으로 전달하십시오.
  • 헹구고 반복하십시오.
  • (필요한 경우 리팩터링하며 테스트 범위가 넓기 때문에 쉬워야합니다.)

이것은 적어도 일부 사람들의 견해로는 거의 최적 코드입니다. 가능한 한 작기 때문에 완성 된 각 기능은 가능한 한 적은 시간이 걸립니다 (완료 된 것을 보았을 때 사실 일 수도 있고 아닐 수도 있음) 리팩토링 후 제품) 및 테스트 범위가 매우 우수합니다. 또한 지나치게 엔지니어링 된 너무 일반적인 메소드 나 클래스를 피할 수 있습니다.

또한 일반적인 사항과 특수한 시점을 명확하게 알려줍니다.

나는 네 도시의 예가 이상하다고 생각한다. 도시 이름을 절대로 하드 코딩하지 않았을 것입니다. 무엇을하든 추가 도시가 나중에 포함될 것임이 분명합니다. 그러나 또 다른 예는 색상입니다. 경우에 따라 "적색"또는 "녹색"하드 코딩이 가능할 수 있습니다. 예를 들어, 신호등은 어디에나있을 수있는 유비쿼터스 색상이며 항상 리팩터링 할 수 있습니다. 차이점은 "빨간색"과 "녹색"은 우리 세계에서 보편적이고 "하드 코딩 된"의미를 가지고 있으며, 그것이 변할 가능성은 거의 없으며, 대안도 없습니다.

첫 번째 일광 절약 방법이 깨졌습니다. 사양을 준수하지만 하드 코딩 된 2018은 a) 기술 "계약"(이 경우 방법 이름으로)에 언급되지 않았으며 b) 곧 만료되어 파손될 수 있기 때문에 특히 나쁩니다. 시작부터 포함됩니다. 시간 / 날짜 관련 사항의 경우 시간이 흐르기 때문에 특정 값을 하드 코딩하는 것이 거의 이치에 맞지 않습니다. 그러나 그 외에는 모든 것이 토론의 대상입니다. 간단한 연도를 제공하고 항상 전체 연도를 계산하는 경우 계속하십시오. 나열된 것 (포맷, 더 작은 범위의 선택 등)의 대부분은 메서드가 너무 많은 것을 비명을 지르고 대신 호출자가 서식 / 필터링을 직접 수행 할 수 있도록 값 목록 / 배열을 반환해야합니다.

그러나 하루가 끝나면 대부분의 의견, 취향, 경험 및 개인적인 편견 때문에 그것에 대해 너무 걱정하지 마십시오.


두 번째 단락부터 마지막 ​​단락까지-처음에 주어진 "요구 사항", 즉 첫 번째 방법이 기반으로 한 요구 사항을 살펴보십시오. 2018을 지정하므로 코드가 기술적으로 정확하며 기능 중심의 접근 방식과 일치 할 수 있습니다.
dwizum

@ dwizum, 요구 사항과 관련하여 정확하지만 메소드 이름이 잘못되었습니다. 2019 년에 메소드 이름을보고있는 프로그래머는 2018이 아닌 모든 것을하고 있다고 가정 할 것입니다 (2018 년이 아닌 현재 연도의 값을 반환 할 수도 있음).
AnoE

1

재사용 가능한 코드에는 두 가지 종류가 있습니다.

  • 기본적이고 기본적인 것이기 때문에 재사용 가능한 코드입니다.
  • 모든 곳에서 매개 변수, 재정의 및 후크가 있으므로 재사용 가능한 코드입니다.

재사용의 첫 번째 종류는 종종 좋은 생각입니다. 목록, 해시 맵, 키 / 값 저장소, 문자열 매처 (예 : 정규식, glob, ...), 튜플, 통합, 검색 트리 (깊이 우선, 너비 우선, 반복 심화 등)에 적용됩니다. , 파서 결합기, 캐시 / 메모리, 데이터 형식 판독기 / 작성기 (s- 표현식, XML, JSON, 프로토 타입 등), 작업 대기열 등

이런 일들은 그래서 그들은 하루 종일 프로그래밍 하루에 여기 저기-재사용 이니까, 매우 추상적 인 방법으로, 일반적으로. 더 추상적이고 일반적인 경우에 더 간단한 특수 목적 코드를 작성하는 경우 (예 : "고객 주문 목록"이있는 경우) "고객 주문"항목을 버려서 "목록"을 얻을 수 있습니다. ) 그렇다면 그것을 꺼내는 것이 좋습니다. 재사용하지 않더라도 관련없는 기능을 분리 할 수 ​​있습니다.

두 번째는 구체적인 문제를 해결하기위한 구체적인 코드가있는 곳이지만 전체 결정을 내려야합니다. 우리는 결정을 매개 변수로 바꾸고 , 구현을 복잡하게 하고 훨씬 더 구체적인 세부 사항 (예 : 재정의를 원하는 후크에 대한 지식)을 결정하는 것과 같이 이러한 결정을 "소프트 코딩"함으로써보다 일반적이고 재사용 가능하게 만들 수 있습니다. 귀하의 예는 이런 종류의 것 같습니다. 이런 종류의 재사용 가능성의 문제는 다른 사람들의 유스 케이스 또는 미래의 자아를 추측하려고 할 수 있다는 것입니다. 결국 우리는 코드를 사용할 수 없을 정도로 많은 매개 변수를 가질 수 있습니다.재사용은 물론! 다시 말해, 호출 할 때 우리 자신의 버전을 작성하는 것보다 더 많은 노력이 필요합니다. YAGNI (You Ai n't Gonna Need It)가 중요한 곳입니다. 많은 경우에, "재사용 가능한"코드에 대한 이러한 시도는 매개 변수가 설명 할 수있는 것보다 더 근본적으로 유스 케이스와 호환되지 않거나 잠재적 사용자가 자신의 역할을 수행 할 수 있기 때문에 재사용되지 않습니다. 거기에는 표준과 라이브러리가 있으며, 그 저자는 "Simple"이라는 단어가 접두어로 붙여 이전 모델과 구별됩니다!).

이 "재사용 성"의 두 번째 형태는 기본적으로 필요에 따라 수행되어야합니다. 물론, "명백한"매개 변수를 사용할 수는 있지만 미래를 예측하기 시작하지는 마십시오. 야 그니.


1 년이라도 하드 코딩 된 첫 번째 테이크가 괜찮다는 데 동의 할 수 있습니까? 또는 해당 요구 사항을 처음 구현 한 경우 연도를 첫 번째 매개 변수로 사용 하시겠습니까?
Koray Tugay

요구 사항은 '무엇을 확인'하는 일회성 스크립트이기 때문에 첫 번째 조치는 훌륭했습니다. 그녀의 '윤리적'테스트는 실패하지만 '도그마없는'테스트는 실패합니다. "그녀는 말할 수 있습니다 ..."는 요구 사항이 아닙니다.
Warbo

우리는 더 많은 정보없이 어느 '도시 파괴'가 "더 낫다"고 말할 수 없다 destroyBaghdad. 아마 어떤 도시가 개선,하지만 경우 것 파괴 destroyBaghdad티그리스 홍수 작품을? 모술과 바스라에서는 재사용 할 수 있지만 메카 나 애틀랜타에서는 재사용 할 수 없습니다.
Warbo

인용문의 주인 인 나다니엘 보렌 슈타인 (Nathaniel Borenstein)에 동의하지 않는 것 같습니다. 나는이 모든 반응과 토론을 읽음으로써 느리게 이해하려고 노력하고 있습니다.
Koray Tugay

1
나는이 차별화를 좋아한다. 항상 명확한 것은 아니며 항상 "테두리 사례"가 있습니다. 그러나 일반적으로, 나는 또한 순수하게 기능 적이고 저수준 인 "빌딩 블록"(종종 static방법의 형태)의 팬이며 , 이와 반대로 "매개 변수 및 후크 구성"에 대한 결정은 일반적으로 일부 구축해야 구조를 정당화 할 수 부탁드립니다.
Marco13

1

이미 훌륭하고 정교한 답변이 많이 있습니다. 그들 중 일부는 구체적인 세부 사항에 깊이 들어가고 일반적으로 소프트웨어 개발 방법론에 대한 특정 견해를 제시하며, 일부는 확실히 논쟁의 여지가있는 요소 또는 "의견"이 뿌려져 있습니다.

Warbo답변은 이미 다른 유형 의 재사용 가능성을 지적했습니다 . 즉, 기본 구성 요소이기 때문에 재사용이 가능한지 또는 어떤 식 으로든 "일반적"이므로 재사용이 가능한지 여부입니다. 후자를 언급하면 재사용 가능성에 대한 일종의 척도 로 고려할 것이 있습니다 .

한 방법이 다른 방법을 에뮬레이트 할 수 있는지 여부

질문의 예와 관련하여 방법이

void dayLightSavings()

고객이 요청한 기능의 구현이었습니다. 따라서 다른 프로그래머가 사용해야 할 것이므로 공개 방법이 될 것입니다.

publicvoid dayLightSavings()

이것은 당신이 당신의 대답에 표시된대로 구현 될 수 있습니다. 이제 누군가 연도를 매개 변수화하려고합니다. 따라서 메소드를 추가 할 수 있습니다

publicvoid dayLightSavings(int year)

원래 구현을 그대로 변경하십시오.

public void dayLightSavings() {
    dayLightSavings(2018);
}

다음 "기능 요청"과 일반화는 동일한 패턴을 따릅니다. 그래서 경우경우에만 가장 일반적인 형태에 대한 수요가, 당신이 가장 일반적인 형태는보다 구체적인 사람의 사소한 구현을 허용 것을 알고, 그것을 구현할 수 있습니다 :

public void dayLightSavings() {
    dayLightSavings(2018, 0, 12, 0, 12, new DateTimeFormatter(...));
}

향후 확장 및 기능 요청이 예상되고 처리 할 시간이 있고 (잠재적으로 쓸모없는) 일반화로 지루한 주말을 보내고 싶다면 가장 일반적인 것부터 시작했을 있습니다. 그러나 개인적인 방법 으로 사용하십시오. 고객이 요청한 간단한 방법 만 공개 방법으로 공개 하는 한 안전합니다.

tl; dr :

문제는 실제로 "어떻게 재사용 할 수 있는가"가 아닙니다. 문제는이 재사용 가능성이 얼마나 많이 노출되고 API가 어떻게 생겼는지입니다. 시간의 테스트를 견딜 수있는 신뢰할 수있는 API를 만드는 것은 (나중에 추가 요구 사항이 나올 때조차도) 예술과 공예이며, 주제를 다루기에는 너무 복잡합니다. 한 번 봐 가지고 여호수아 블로흐이 프레젠테이션 또는 API를 설계 도서 위키 시작에 대한합니다.


dayLightSavings()전화 dayLightSavings(2018)는 나에게 좋은 생각처럼 보이지 않습니다.
Koray Tugay

@KorayTugay 초기 요청에 "2018 년 일광 절약 시간제"를 인쇄해야 할 경우에는 문제가 없습니다. 사실, 이것은 입니다 원래 구현 방법은 정확히. " 현재 연도의 일광 절약 시간제를 인쇄해야하는 경우 당연히 전화하십시오 dayLightSavings(computeCurrentYear());. ...
Marco13

0

경험상 가장 좋은 방법은 다음과 같습니다. 방법은 재사용 할 수 있어야합니다.

한 곳에서만 메소드를 호출 할 것으로 예상되는 경우, 호출 사이트에 알려지고이 메소드에서 사용할 수없는 매개 변수 만 있어야합니다.

더 많은 발신자가있는 경우 다른 발신자가 해당 매개 변수를 전달할 수있는 한 새 매개 변수를 도입 할 수 있습니다. 그렇지 않으면 새로운 방법이 필요합니다.

발신자의 수가 시간이 지남에 따라 리팩토링 또는 과부하에 대비해야합니다. 대부분의 경우 IDE의 표현식을 선택하고“추출 매개 변수”작업을 실행하는 것이 안전하다고 생각해야합니다.


0

매우 짧은 대답 : 일반 모듈의 다른 코드와결합 또는 종속성 이 적을수록 재사용 가능성이 높아집니다.

귀하의 예는 다음에 만 의존합니다

import java.time.*;
import java.util.Set;

이론적으로는 재사용 성이 높습니다.

실제로 나는 당신 이이 코드를 필요로하는 두 번째 유스 케이스를 가질 것이라고 생각하지 않으므로 yagni 원리에 따라이 코드가 필요한 3 가지 이상의 다른 제트기 가 없다면 재사용 할 수 없게됩니다.

재사용 성의 다른 측면은 테스트 중심 개발 과 관련이있는 사용의 용이성 및 두 큐멘 테이션입니다 . lib를 사용하는 사용자를위한 코딩 예제로 일반 모듈을 쉽게 사용하는 방법을 보여주는 간단한 단위 테스트가 있으면 도움이됩니다.


0

이것은 내가 최근에 만든 규칙을 말할 수있는 좋은 기회입니다.

좋은 프로그래머가된다는 것은 미래를 예측할 수 있다는 것을 의미합니다.

물론 이것은 불가능합니다! 결국, 당신은 확실 하지 않습니다 어떤 일반화에 유용한 지, 수행 할 관련 작업, 사용자가 원하는 새로운 기능 등 . 그러나 경험에 따라 때로는 유용한 것이 무엇인지 대략 알 수 있습니다.

그와 균형을 유지해야하는 다른 요소는 추가 시간과 노력이 얼마나 들며 코드를 얼마나 복잡하게 만드는가입니다. 때로는 운이 좋으며 더 일반적인 문제를 해결하는 것이 실제로 더 간단합니다! (적어도 개념적으로는 코드의 양이 아닌 경우). 그러나 시간과 노력 중 하나뿐만 아니라 복잡성 비용이 더 자주 발생합니다.

따라서 일반화가 필요할 가능성이 높다고 생각되면, 많은 것을 추가하지 않는 한 종종 가치가 있습니다 작업이나 복잡성을 . 그러나 훨씬 덜 가능성이 있다면 아마도 아닐 것입니다 (매우 쉽고 코드가 간단하지 않으면).

(최근 예 : 지난 주에 시스템이 만료 된 후 정확히 2 일이 걸리는 작업에 대한 사양이 주어졌습니다. 물론 2 일 기간을 매개 변수로 만들었습니다. 이번 주에는 비즈니스 사람들이 기뻐했습니다. 나는 운이 좋았다 : 쉬운 변화 였고, 그것이 원치 않을 것이라고 생각했다. 종종 판단하기가 어렵지만, 여전히 예측하려고 노력할 가치가 있으며, 경험은 종종 좋은 가이드이다. .)


0

첫째, '내 방법이 어떻게 재사용되어야하는지 어떻게 알 수 있습니까?'에 대한 가장 좋은 대답은 "경험"입니다. 수천 번 정도하면 보통 답을 얻을 수 있습니다. 그러나 티저로서 이 답변의 라인 : 고객은 얼마나 많은 유연성과 일반화 계층을 찾아야하는지 알려줄 것입니다.

이 답변들 중 다수에는 구체적인 조언이 있습니다. 아이러니가 너무 재미있어서 좀 더 일반적인 것을주고 싶었습니다!

일부 답변에서 언급했듯이 일반성은 비쌉니다. 그러나 실제로는 그렇지 않습니다. 항상 그런 것은 아닙니다. 재사용 성 게임을 플레이하려면 비용을 이해해야합니다.

나는 "돌이킬 수없는"에서 "가역적 인"에 이르는 규모로 물건을 놓는 데 집중합니다. 부드러운 규모입니다. 진정으로 돌이킬 수없는 유일한 것은 "프로젝트에 소요 된 시간"입니다. 그런 자원을 다시는 얻지 못할 것입니다. 약간 덜 가역적 인 것은 Windows API와 같은 "골든 수갑"상황 일 수 있습니다. 더 이상 사용되지 않는 기능은 Microsoft의 비즈니스 모델이 요구하기 때문에 수십 년 동안 API에 남아 있습니다. 일부 API 기능을 실행 취소하여 관계가 영구적으로 손상 될 고객이있는 경우 되돌릴 수없는 것으로 처리해야합니다. 스케일의 다른 쪽 끝을 보면 프로토 타입 코드와 같은 것이 있습니다. 가는 곳이 마음에 들지 않으면 그냥 버릴 수 있습니다. 내부 사용 API가 약간 덜 가역적 일 수 있습니다. 고객을 방해하지 않고 리팩토링 할 수 있습니다.시간 (모두의 가장 돌이킬 수없는 자원!)

그래서 이것들을 스케일에 넣으십시오. 이제 휴리스틱을 적용 할 수 있습니다. 가역성이 높을수록 향후 활동에 더 많이 사용할 수 있습니다. 돌이킬 수없는 것이 있으면 구체적인 고객 중심 작업에만 사용하십시오. 그렇기 때문에 고객이 요구하는 것만 수행 할 것을 제안하는 극단적 인 프로그래밍과 같은 원칙을 볼 수 있습니다. 이 원칙들은 당신이 후회하는 일을하지 않도록하는 데 탁월합니다.

DRY 원칙과 같은 것들이 그 균형을 움직일 수있는 방법을 제안합니다. 스스로 반복하는 것을 발견하면 기본적으로 내부 API를 만들 수있는 기회입니다. 고객이 보지 않으므로 언제든지 변경할 수 있습니다. 이 내부 API가 있으면 이제는 미래를 내다 보는 게임을 시작할 수 있습니다. 아내가 몇 가지 시간대 기반 작업을 제공한다고 생각하십니까? 시간대 기반 작업을 원하는 다른 고객이 있습니까? 귀하의 유연성은 현재 고객의 구체적인 요구에 의해 구매되며 미래 고객의 잠재적 미래 요구를 지원합니다.

DRY에서 자연스럽게 제공되는이 계층 적 사고 방식은 자연스럽게 낭비없이 원하는 일반화를 제공합니다. 그러나 한계가 있습니까? 물론 있습니다. 그러나 그것을 보려면 나무의 숲을 봐야합니다.

융통성이 많은 계층이있는 경우 고객이 직면하는 계층을 직접 제어 할 수없는 경우가 많습니다. 나는 고객이 볼 수 없었던 10 층으로 구성된 유연성으로 인해 원하는 것을 가질 수없는 이유를 고객에게 설명하는 잔인한 작업을했던 소프트웨어를 가지고있었습니다. 우리는 모퉁이에 자신을 썼습니다. 우리는 우리가 필요하다고 생각한 모든 유연성으로 매듭을 묶었습니다.

따라서이 일반화 / 건조 트릭을 수행 할 때는 항상 고객에게 항상 관심을 가져야 합니다 . 아내가 다음에 무엇을 요구할 것이라고 생각하십니까? 그러한 요구를 충족시킬 수있는 입장에 서십니까? 요령이 있다면 고객은 미래의 요구를 효과적으로 알려줍니다. 요령이 없다면 대부분의 사람들은 추측에 의존합니다! (특히 배우자와 함께!) 일부 고객은 뛰어난 유연성을 원하며 이러한 모든 레이어로 개발하는 데 드는 추가 비용을 기꺼이 받아 들일 수 있습니다. 다른 고객은 확고한 요구 사항을 수정했으며 개발이 더 직접적인 것을 선호합니다. 고객은 얼마나 많은 유연성과 일반화 계층을 찾아야하는지 알려줄 것입니다.


이 10000 번을 한 다른 사람들이 있어야하는데, 왜 10000 번을하고 다른 사람들로부터 배울 수있을 때 경험을 얻어야합니까? 답변은 개인마다 다르므로 경험있는 답변은 저에게 적용되지 않습니까? 또한 Your customer will tell you how much flexibility and how many layers of generalization you should seek.이 세상은 무엇입니까?
Koray Tugay

@KorayTugay 비즈니스 세계입니다. 고객이해야 할 일을 말하지 않으면 충분히 듣지 못하는 것입니다. 물론, 그들은 항상 당신에게 말로 말하지는 않지만 다른 방법으로 당신에게 말합니다. 경험을 통해보다 미묘한 메시지를들을 수 있습니다. 아직 기술이 없다면 회사에서 그 미묘한 고객의 힌트를들을 수있는 기술을 가진 사람을 찾아 지시를 구하십시오. 그들이 CEO이거나 마케팅에 있어도 그 기술을 가진 사람이있을 것입니다.
Cort Ammon

특정 경우에 특정 솔루션을 해킹하는 대신이 표준 시간대 문제의 일반화 된 버전을 코딩하는 데 너무 바빠서 쓰레기를 꺼내지 못한 경우 고객은 어떻게 느끼겠습니까?
Cort Ammon

그래서 당신은 내 첫 번째 접근 방식이 올바른 방법이라는 데 동의합니다 .2018 년을 매개 변수 대신 첫 번째 코드로 하드 ​​코딩하는 것입니까? (btw, 그건 내 고객의 말을 듣지 않는 것입니다. 쓰레기 예제입니다. 고객을 아는 것입니다.) Oracle의 지원을 받더라도 일광 목록이 필요하다고 할 때들을 수있는 미묘한 메시지는 없습니다 시간을 내 주셔서 감사합니다. btw.
Koray Tugay

@KorayTugay 자세한 내용을 알지 못하면 하드 코딩이 올바른 방법이라고 생각합니다. 미래의 DLS 코드가 필요한지, 다음에 어떤 종류의 요청을할지 전혀 알지 못했습니다. 그리고 고객이 당신을 시험하려고하면, 그들이 얻는 것을 얻을 수 있습니다.
Cort Ammon

0

윤리적으로 훈련 된 소프트웨어 엔지니어는 DestroyBaghdad 절차 작성에 동의하지 않습니다. 기본적인 전문 윤리는 그 대신 바그다드를 매개 변수로 제공 할 수있는 DestroyCity 절차를 작성해야합니다.

이것은 고급 소프트웨어 엔지니어링 분야에서 "농담"으로 알려진 것입니다. 농담은 우리가 "참"이라고 부르는 것일 필요는 없지만, 재미 있기는하지만 일반적으로 사실을 암시해야합니다.

이 특별한 경우에, "농담"은 "참"이 아니다. 파괴하는 일반적인 절차를 서면으로 관련된 일 모든 도시는, 우리는 안전하게 하나를 파괴하기 위해 요구되는 것 이상으로, 크기 순서를 가정 할 수있다 특정을시티. 그렇지 않으면, 한 도시 또는 소수의 도시 (성경의 여호수아, 우리가 말할 것, 또는 트루먼 (Truman))를 파괴 한 사람은 자신이 한 일을 사소하게 일반화 할 수 있고 마음대로 모든 도시를 파괴 할 수 있습니다. 사실 이것은 사실이 아닙니다. 소수의 특정 도시를 파괴하기 위해 그 두 사람이 유명하게 사용했던 방법이 항상 어떤 도시에서도 작동하지는 않습니다. 벽의 공진 주파수가 다르거 나 고도 방공이 더 나은 다른 도시는 접근 방식이 약간 또는 근본적으로 변경 될 필요가 있습니다 (서로 다른 트럼펫 또는 로켓).

이것은 또한 시간이 지남에 따른 변화에 대비 한 코드 유지 관리로 이어진다. 현대의 건설 방법과 유비쿼터스 레이더 덕분에 지금은 그다지 접근하지 않는 도시가 많이있다.

개발 및 파괴 완전히 일반적인 수단 테스트 어떤 그냥 데스트에 동의하기 전에, 도시를 하나 개의 도시를, 필사적으로 비효율적 인 방법입니다. 윤리적으로 훈련 된 소프트웨어 엔지니어는 입증 된 요구 사항없이 고용주 / 고객이 실제로 지불해야하는 것보다 훨씬 더 많은 작업을 요구하는 정도로 문제를 일반화하려고 시도하지 않습니다.

그래서 사실은 무엇입니까? 때때로 일반성을 추가하는 것은 사소한 일입니다. 그렇게하기에는 항상 일반성을 추가해야합니까? 나는 장기적인 유지 보수 문제 때문에 여전히 "항상 그런 것은 아니다"라고 주장 할 것이다. 글을 쓰는 시점에서 모든 도시가 기본적으로 동일하다고 가정하므로 DestroyCity로 넘어갑니다. 이것을 작성하면 (연히 열거 가능한 입력 공간으로 인한) 통합 테스트와 함께 알려진 모든 도시를 반복하고 함수가 각 도시에서 작동하는지 확인하십시오 (어떻게 작동하는지 확실하지 않습니다. 아마도 City.clone () 및 복제품을 파괴합니까?

실제로이 기능은 바그다드를 파괴하기 위해서만 사용됩니다. 누군가 내 기술 (지하 깊은 곳)에 저항하는 새로운 도시를 건설한다고 가정합니다. 이제는 실제로 존재하지 않는 유스 케이스에 대한 통합 테스트 실패가 발생 했으며 무고한 이라크 인 민간인에 대한 테러 캠페인을 계속하기 전에 지하를 파괴하는 방법을 찾아야합니다. 이것이 윤리적인지 아닌지는 신경 쓰지 마십시오. 그것은 바보 같은 짓 이며 시간을 낭비합니다 .

그래서, 당신은 정말 기능 출력 할 수 있습니다 일광 절약할까요 어떤 단지 2018에 대한 데이터를 출력 해,? 어쩌면 테스트 케이스를 구성하는 데 약간의 추가 노력이 필요할 것입니다. 실제보다 더 나은 시간대 데이터베이스를 얻으려면 많은 노력이 필요할 수 있습니다. 예를 들어, 1908 년 온타리오 주 포트 아서 (Port Arthur)는 7 월 1 일에 DST 기간을 시작했습니다. OS 시간대 데이터베이스에 있습니까? 생각하지 않았으므로 일반화 된 기능이 잘못되었습니다 . 유지할 수 없다고 약속하는 코드를 작성하는 데 특히 윤리적 인 것은 없습니다.

알 맞습니다. 적절한 경고를하면 1970- 현재의 날짜와 같이 몇 년 동안 시간대를 수행하는 함수를 쉽게 작성할 수 있습니다. 그러나 실제로 작성한 기능을 사용하고 연도를 매개 변수화하기 위해 일반화하는 것도 쉽습니다. 그러므로 지금 일반화하는 것이 더 윤리적이거나 현명한 것은 아닙니다. 그것은 당신이 한 일을하고 필요할 때 언제 그리고 나 일반화하는 것입니다.

그러나 부인이이 DST 목록을 확인하려는 이유 를 알고 있다면 2019 년에 다시 같은 질문을 할 가능성이 있는지 여부와 정보를 제공함으로써 해당 루프에서 벗어날 수 있는지에 대한 정보를 얻을 수 있습니다. 그녀는 다시 컴파일 할 필요없이 호출 할 수있는 함수입니다. 분석을 마치면 "최근 몇 년 동안 일반화해야합니까?"라는 질문에 대한 대답은 "예"일 수 있습니다. 그러나 미래의 시간대 데이터는 잠정적이므로 오늘 2019 년에 실행하는 경우에도 또 다른 문제가 발생 합니다., 그녀는 그것이 그녀에게 최고의 추측을 제공하고 있음을 인식하거나 인식하지 못할 수 있습니다. 따라서 여전히 덜 일반적인 기능에 필요하지 않은 많은 문서를 작성해야합니다 ( "데이터는 표준 데이터베이스에서 제공됩니다. 여기에서 업데이트를 추진하는 정책을 볼 수있는 링크가 있습니다"). 특별한 경우를 거부하면, 당신이 그렇게하는 모든 시간에, 그녀는 2019 년에 대한 약간의 넌센스 때문에 아직 신경 쓰지 않는 2018 데이터가 필요한 작업을 계속할 수 없습니다.

농담이 당신에게 말했기 때문에 제대로 생각하지 않고 어려운 일을하지 마십시오. 유용합니까? 그 정도의 유용성이 충분히 저렴합니까?


0

건축 우주 비행사에 의해 정의 된 재사용 성은 볼록이기 때문에 이것은 쉽게 그릴 수 있습니다.

응용 프로그램 개발자가 만든 거의 모든 코드는 도메인마다 매우 다릅니다. 이것은 1980 년이 아닙니다. 귀찮게하는 거의 모든 것이 이미 틀에 있습니다.

추상화와 규칙에는 문서화와 학습 노력이 필요합니다. 그것을 위해서만 새로운 것을 만드는 것을 중지하십시오. (나는 당신을보고 있습니다 , JavaScript 사람들!)

선택한 프레임 워크에 진정으로 필요한 것을 발견 한 끔찍한 환상에 빠지도록합시다. 평소와 같이 코드를 작성하지 않아도됩니다. 아뇨, 당신은 의도 된 사용뿐만 아니라 의도 된 사용으로부터의 출발, 알려진 모든 엣지 케이스, 상상할 수있는 모든 실패 모드, 진단을위한 테스트 케이스, 테스트 데이터, 기술 문서, 사용자 문서, 릴리스 관리, 지원을위한 테스트 범위가 필요합니다 스크립트, 회귀 테스트, 변경 관리 ...

고용주는 그 모든 것에 대해 기꺼이 돈을 지불합니까? 나는 아니오라고 말할 것입니다.

추상화는 유연성을 위해 지불하는 가격입니다. 코드를 더 복잡하고 이해하기 어렵게 만듭니다. 유연성이 실질적이고 현재의 요구에 부응하지 않는 한 YAGNI이기 때문에 그렇지 않습니다.

방금 처리해야하는 실제 예인 HTMLRenderer를 살펴 보겠습니다. 프린터의 장치 컨텍스트로 렌더링하려고 할 때 제대로 확장되지 않았습니다. 내가 발견하기 전에 두 어셈블리에서 6 단계의 간접 지시를 통과해야했기 때문에 기본적으로 GDI + (확장하지는 않지만 앤티 앨리어스) 대신 GDI (확장되지 않음)를 사용하고 있음을 발견하는 데 하루 종일 걸렸습니다. 아무것도 한 코드 .

이 경우 저자를 용서하겠습니다. 추상화는 실제로 필요한 이 있기 때문 이다 윈폼, WPF, DOTNET 코어, 모노 및 PdfSharp : 다섯 개 매우 다른 렌더링 타겟을 대상으로 프레임 워크 코드.

그러나 그것은 내 요점을 강조 합니다. 모든 플랫폼에서 고성능이라는 명시된 목표로 여러 플랫폼을 대상으로 매우 복잡한 작업 (스타일 시트를 사용한 HTML 렌더링)을 수행 하지 않을 것입니다.

귀하의 코드는 거의 확실하게 고용주에게만 적용되는 비즈니스 규칙과 판매용이 아닌 응용 프로그램에서 해당 주에만 적용되는 세금 규칙을 가진 또 다른 데이터베이스 그리드입니다.

모든 것은 간접 문제는 없습니다를 해결하고 코드를 만드는 많은 대규모 유지 보수의 비용을 증가시키고 고용주에 큰 끼치는 인, 읽기 어렵습니다. 운좋게도 이것에 대해 불평해야하는 사람들은 당신이 그들에게하고있는 일을 이해할 수 없습니다.

반박 론은 이러한 종류의 추상화가 테스트 주도 개발을 지원한다는 것입니다. 그러나 TDD는 비즈니스가 요구 사항을 명확하고 완전하며 올바르게 이해하고 있음을 전제로하기 때문에 볼록하다고 생각합니다. TDD는 NASA 및 의료 기기 및 자율 주행 차량용 제어 소프트웨어에 적합하지만 다른 사람에게는 너무 비쌉니다.


또한 세계의 모든 일광 절약 시간 을 예측할 수는 없습니다 . 특히 이스라엘은 매년 약 40 회의 변화를 겪고 있는데, 우리는 잘못된 시간에기도하는 사람들을 가질 수없고 신은 일광 절약을하지 않기 때문입니다.


추상화와 학습 노력에 대해, 특히 "자바 스크립트"라는 혐오를 목표로하는 내용에 동의하지만 첫 문장에 동의하지 않아야합니다. 재사용 가능성은 여러 수준에서 발생할 수 있으며 너무 멀리 떨어질 수 있습니다. 수 있으며, 버리기 프로그래머는 버리기 코드를 작성할 수 있습니다. 그러나이 있다 적어도 충분히 이상주의적인 사람들 의 목표 재사용 가능한 코드에가. 이것이 가질 수있는 혜택을 보지 못한 경우 유감입니다.
Marco13

@ Marco13-귀하의 이의가 합리적이므로 요점을 확장하겠습니다.
Peter Wone

-3

Java 8 이상을 사용하는 경우 본질적으로 시간대 모음으로 보이는 것을 제공하기 위해 WorldTimeZones 클래스를 작성합니다.

그런 다음 WorldTimeZones 클래스에 filter (Predicate filter) 메소드를 추가하십시오. 이를 통해 호출자는 람다 식을 매개 변수로 전달하여 원하는 것을 필터링 할 수 있습니다.

본질적으로 단일 필터 방법은 술어에 전달 된 값에 포함 된 모든 항목에 대한 필터링을 지원합니다.

또는 WorldTimeZones 클래스에 stream () 메소드를 추가하여 호출 될 때 시간대 스트림을 생성합니다. 그런 다음 발신자는 전문화를 전혀 작성하지 않고도 원하는대로 필터링, 매핑 및 축소 할 수 있습니다.


3
이것들은 좋은 일반화 아이디어이지만이 답변은 질문에서 요구되는 것에 대한 표시를 완전히 놓친 것입니다. 문제는 솔루션을 가장 잘 일반화하는 방법이 아니라 일반화에서 선을 그리는 위치와 이러한 고려 사항을 윤리적으로 평가하는 방법에 관한 것입니다.
maple_shaft

그래서 나는 창조의 복잡성에 의해 수정 된 지원 사례의 수에 따라 그것들을 평가해야한다고 말하고 있습니다. 하나의 사용 사례를 지원하는 방법은 20 개의 사용 사례를 지원하는 방법만큼 가치가 없습니다. 반면에, 아는 것이 하나의 유스 케이스 인 경우 코딩하는 데 5 분이 걸립니다. 특정 용도를 지원하는 코딩 방법은 일반화 방법을 알려줍니다.
로드니 P. 바바 티
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.