태그 보관물: programming-practices

programming-practices

재사용 가능한 방법을 어떻게 알 수 있습니까? [닫은] 나는 집에서 내

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

여보 .. 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);

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



답변

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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).

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

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

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


답변

연습

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

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

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

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

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

지침 2 : 비용 / 혜택

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

지침 3 : 상수에 초점

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


답변

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

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

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

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

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

셋째 :

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

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

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

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

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

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

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

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

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


답변

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

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

그래서 당신의 기능에서

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 인스턴스에 문의해야합니다. 백 로그에 기록하고 적절한 프로젝트 관리위원회 회의에서 우선 순위를 지정할 수 있습니다.


답변

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

제공 한 예제만큼 단순한 것은 초기 구현은 크기가 작기 때문에 훌륭하지만, 이처럼 단순한 디자인은 너무 많은 기능적 유연성 (설계 유연성이 아닌)을 방해하면 이해하기 어렵고 부서지기 쉽습니다. 하나의 절차. 아래는 이해와 유연성을 위해 복잡한 시스템을 설계하는 데 선호되는 접근 방식에 대한 설명입니다. 이 절차는 단일 절차에서 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()
            );
        });
    }
}

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


답변

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

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


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

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

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

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


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

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

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

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


답변

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

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

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

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

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