খুব জটিল পদ্ধতি এড়িয়ে চলুন - সাইক্লোমেটিক জটিলতা


23

সাইক্লোমেটিক জটিলতা কমাতে এই পদ্ধতিটি কীভাবে করবেন তা নিশ্চিত নন। সোনার ১৩ টি রিপোর্ট করেছে এবং 10 টি প্রত্যাশিত। আমি নিশ্চিত যে এই পদ্ধতিটি যেমন রয়েছে তেমনি রেখে যাওয়ার কোনও ক্ষতি নেই তবে যাইহোক, সোনার বিধি মানার বিষয়ে কীভাবে চলতে হবে তা কেবল আমাকে চ্যালেঞ্জ করে। যেকোনো বুদ্ধিই চমৎকারভাবে গ্রহন করা হবে।

 public static long parseTimeValue(String sValue) {

    if (sValue == null) {
        return 0;
    }

    try {
        long millis;
        if (sValue.endsWith("S")) {
            millis = new ExtractSecond(sValue).invoke();
        } else if (sValue.endsWith("ms")) {
            millis = new ExtractMillisecond(sValue).invoke();
        } else if (sValue.endsWith("s")) {
            millis = new ExtractInSecond(sValue).invoke();
        } else if (sValue.endsWith("m")) {
            millis = new ExtractInMinute(sValue).invoke();
        } else if (sValue.endsWith("H") || sValue.endsWith("h")) {
            millis = new ExtractHour(sValue).invoke();
        } else if (sValue.endsWith("d")) {
            millis = new ExtractDay(sValue).invoke();
        } else if (sValue.endsWith("w")) {
            millis = new ExtractWeek(sValue).invoke();
        } else {
            millis = Long.parseLong(sValue);
        }

        return millis;

    } catch (NumberFormatException e) {
        LOGGER.warn("Number format exception", e);
    }

    return 0;
}

সমস্ত এক্সট্রাক্ট এক্সএক্সএক্স পদ্ধতিগুলি staticঅভ্যন্তর শ্রেণি হিসাবে সংজ্ঞায়িত করা হয় । উদাহরণস্বরূপ, নীচের মত একটি -

    private static class ExtractHour {
      private String sValue;

      public ExtractHour(String sValue) {
         this.sValue = sValue;
      }

      public long invoke() {
         long millis;
         millis = (long) (Double.parseDouble(sValue.substring(0, sValue.length() - 1)) * 60 * 60 * 1000);
         return millis;
     }
 }

আপডেট 1

আমি সোনার লোককে সন্তুষ্ট করতে এখানে পরামর্শের মিশ্রণ নিয়ে বসতি স্থাপন করব। অবশ্যই উন্নতি এবং সরলীকরণের জন্য জায়গা।

পেয়ারা Functionএখানে কেবল একটি অযাচিত অনুষ্ঠান। বর্তমান অবস্থা সম্পর্কে প্রশ্ন আপডেট করতে চেয়েছিলেন। এখানে কিছুই চূড়ান্ত নয়। আপনার চিন্তা Pালা দয়া করে ..

public class DurationParse {

private static final Logger LOGGER = LoggerFactory.getLogger(DurationParse.class);
private static final Map<String, Function<String, Long>> MULTIPLIERS;
private static final Pattern STRING_REGEX = Pattern.compile("^(\\d+)\\s*(\\w+)");

static {

    MULTIPLIERS = new HashMap<>(7);

    MULTIPLIERS.put("S", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractSecond(input).invoke();
        }
    });

    MULTIPLIERS.put("s", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractInSecond(input).invoke();
        }
    });

    MULTIPLIERS.put("ms", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractMillisecond(input).invoke();
        }
    });

    MULTIPLIERS.put("m", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractInMinute(input).invoke();
        }
    });

    MULTIPLIERS.put("H", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractHour(input).invoke();
        }
    });

    MULTIPLIERS.put("d", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractDay(input).invoke();
        }
    });

    MULTIPLIERS.put("w", new Function<String, Long>() {
        @Nullable
        @Override
        public Long apply(@Nullable String input) {
            return new ExtractWeek(input).invoke();
        }
    });

}

public static long parseTimeValue(String sValue) {

    if (isNullOrEmpty(sValue)) {
        return 0;
    }

    Matcher matcher = STRING_REGEX.matcher(sValue.trim());

    if (!matcher.matches()) {
        LOGGER.warn(String.format("%s is invalid duration, assuming 0ms", sValue));
        return 0;
    }

    if (MULTIPLIERS.get(matcher.group(2)) == null) {
        LOGGER.warn(String.format("%s is invalid configuration, assuming 0ms", sValue));
        return 0;
    }

    return MULTIPLIERS.get(matcher.group(2)).apply(matcher.group(1));
}

private static class ExtractSecond {
    private String sValue;

    public ExtractSecond(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = Long.parseLong(sValue);
        return millis;
    }
}

private static class ExtractMillisecond {
    private String sValue;

    public ExtractMillisecond(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue));
        return millis;
    }
}

private static class ExtractInSecond {
    private String sValue;

    public ExtractInSecond(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue) * 1000);
        return millis;
    }
}

private static class ExtractInMinute {
    private String sValue;

    public ExtractInMinute(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue) * 60 * 1000);
        return millis;
    }
}

private static class ExtractHour {
    private String sValue;

    public ExtractHour(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue) * 60 * 60 * 1000);
        return millis;
    }
}

private static class ExtractDay {
    private String sValue;

    public ExtractDay(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue) * 24 * 60 * 60 * 1000);
        return millis;
    }
}

private static class ExtractWeek {
    private String sValue;

    public ExtractWeek(String sValue) {
        this.sValue = sValue;
    }

    public long invoke() {
        long millis;
        millis = (long) (Double.parseDouble(sValue) * 7 * 24 * 60 * 60 * 1000);
        return millis;
    }
}

}


আপডেট 2

যদিও আমি আমার আপডেট যুক্ত করেছি, তবে এটি কেবল সময়ের মূল্য মাত্র। সোনার এখন যেহেতু অভিযোগ করে না সেহেতু আমি এগিয়ে যাচ্ছি। খুব বেশি চিন্তা করবেন না এবং আমি ম্যাটঞ্জ উত্তরটি গ্রহণ করি কারণ এটি যাওয়ার উপায় এবং যারা এই প্রশ্নটির দিকে ঝাঁপিয়ে পড়ে তাদের পক্ষে কোনও খারাপ উদাহরণ স্থাপন করতে চাই না। নীচের লাইন - সোনার (বা হাফ বেকড প্রজেক্ট ম্যানেজার) স্বার্থের জন্য ওভার ইঞ্জিনিয়ারকে সিসির বিরুদ্ধে অভিযোগ করবেন না। প্রকল্পের জন্য কেবল এক পয়সা মূল্যবান জিনিসই করুন। সবাইকে ধন্যবাদ.


4
সহজতম ওও উত্তর অফহান: private static Dictionary<string,Func<string,long>> _mappingStringToParser;আমি আপনার জন্য ব্যায়াম হিসাবে বাকীটি ছেড়ে দেব (বা এই মুহুর্তে আমার চেয়ে বেশি সময় ব্যয়কারী)। মোনাডিক পার্সারগুলির সাথে আপনার কোনও পরিচিতি থাকলে সেখানে একটি ক্লিনার এপিআই পাওয়া যাবে তবে আমি এখনই সেখানে যাব না
জিমি হোফা

আপনি যদি "মোনাডিক পার্সার্স" এবং কিছুটা কীভাবে এটির মতো ছোট্ট ফাংশনে প্রয়োগ করতে পারেন তবে কীভাবে কিছুটা বাদ দিতে পারতেন তা পছন্দ করবে। এবং কোডের এই অংশটি জাভা থেকে এসেছে।
asyncwait

ExtractBlahক্লাসগুলি কীভাবে সংজ্ঞায়িত করা হয়? এগুলি কিছু লাইব্রেরি বা হোমব্রু থেকে এসেছে?
gnat

4
সংযুক্ত কোডটি আমাকে আরও একটি সহজ বাস্তবায়নের দিকে নিয়ে যায়: আপনার আসল প্রকরণটি গুণক। এগুলির একটি মানচিত্র তৈরি করুন: আপনার sValue এর প্রান্ত থেকে আলফা অক্ষরগুলি টানুন, সেগুলি আপনার কী হিসাবে ব্যবহার করুন এবং তারপরে ম্যাপযুক্ত গুণক দ্বারা একাধিক মানটির জন্য সামনে থেকে আলফাগুলি সমস্ত টানুন।
জিমি হোফা

2
পুনরায় আপডেট: আমিই কি কেবলমাত্র একজন যার মাথায় "ওভার ইঞ্জিনিয়ার্ড" বেজেছে?
mattnz

উত্তর:


46

সফটওয়্যার ইঞ্জিনিয়ারিং উত্তর:

এটি এমন অনেকগুলি ক্ষেত্রে কেবল একটি যেখানে সিম গণনা করা সহজ যা আপনাকে ভুল কাজ করতে বাধ্য করে simple এটি কোনও জটিল কাজ নয়, এটি পরিবর্তন করবেন না। সাইক্লোমেটিক জটিলতা কেবল জটিলতার জন্য গাইড এবং আপনি যদি এটির ভিত্তিতে এই ফাংশনটি পরিবর্তন করেন তবে আপনি এটি খারাপ ব্যবহার করছেন। এটি এর সহজ, এটি পঠনযোগ্য, এটি রক্ষণাবেক্ষণযোগ্য (আপাতত), যদি ভবিষ্যতে এটি আরও বড় হয় তবে সিসি তাত্পর্যপূর্ণভাবে আকাশ ছোঁড়া করবে এবং এটি যখন প্রয়োজন তখন এটির মনোযোগ প্রয়োজন যখন এটি প্রয়োজন হবে না।

মিয়ানম একটি বৃহত্তর বহুজাতিক কর্পোরেশনের জন্য কাজ করছে উত্তর:

সংস্থাগুলি শিম কাউন্টারগুলির অতিরিক্ত বেতনভোগী, অনুপাতহীন দলগুলিতে পূর্ণ। শিম কাউন্টারগুলিকে খুশি রাখা সঠিক কাজ করার চেয়ে সহজ এবং অবশ্যই বুদ্ধিমান। তাকে সিসি নামিয়ে 10 এ নামানোর জন্য আপনাকে রুটিন পরিবর্তন করতে হবে, তবে কেন আপনি এটি করছেন তা সম্পর্কে সৎ হন - শিম কাউন্টারগুলি আপনার পিছনে রাখার জন্য। মন্তব্যে প্রস্তাবিত হিসাবে - "মোনাডিক পার্সারস" সহায়তা করতে পারে


14
নিয়মের কারণকে সম্মান করার জন্য +1, নিয়ম নিজেই নয়
রাদু মুর্জিয়া

5
ভাল বলেছ! তবে অন্যান্য ক্ষেত্রে যেখানে আপনার বেশ কয়েকটি বাসা বাঁধার স্তর এবং জটিল (ব্রাঞ্চিং) যুক্তি সহ সিসি = 13 রয়েছে এটি অন্তত সরল করার চেষ্টা করা ভাল।
গ্রিজওয়াকো

16

তাদের সহায়তার জন্য @ জিমিহোফা, @ মিশেলটি, এবং @ গ্লেনএইচ 7 কে ধন্যবাদ!

পাইথন

প্রথম জিনিসগুলি, আপনার কেবলমাত্র পরিচিত উপসর্গগুলি গ্রহণ করা উচিত, এটি হয় 'এইচ' বা 'এইচ'। আপনি যদি আছে উভয় গ্রহণ করতে, আপনি এটি আপনার মানচিত্রে রুম সংরক্ষণ করতে সঙ্গতিপূর্ণ করার কিছু অপারেশন সম্পাদন করা উচিত।

পাইথনে আপনি একটি অভিধান তৈরি করতে পারেন।

EXTRACTION_MAP = {
    'S': ExtractSecond,
    'ms': ExtractMillisecond,
    'm': ExtractMinute,
    'H': ExtractHour,
    'd': ExtractDay,
    'w': ExtractWeek
}

তারপরে আমরা পদ্ধতিটি এটি ব্যবহার করতে চাই:

def parseTimeValue(sValue)
    ending = ''.join([i for i in sValue if not i.isdigit()])
    return EXTRACTION_MAP[ending](sValue).invoke()

একটি আরও ভাল চক্রযুক্ত জটিলতা থাকা উচিত।


জাভা

আমাদের প্রতিটি গুণক মাত্র 1 (এক) প্রয়োজন। কিছু অন্যান্য উত্তরের পরামর্শ অনুসারে এগুলি মানচিত্রে রাখি Le

Map<String, Float> multipliers = new HashMap<String, Float>();
    map.put("S", 60 * 60);
    map.put("ms", 60 * 60 * 1000);
    map.put("m", 60);
    map.put("H", 1);
    map.put("d", 1.0 / 24);
    map.put("w", 1.0 / (24 * 7));

তারপরে আমরা ডান রূপান্তরকারীটি দখল করতে মানচিত্রটি ব্যবহার করতে পারি

Pattern foo = Pattern.compile(".*(\\d+)\\s*(\\w+)");
Matcher bar = foo.matcher(sValue);
if(bar.matches()) {
    return (long) (Double.parseDouble(bar.group(1)) * multipliers.get(bar.group(2);
}

হ্যাঁ, একটি রূপান্তর ফ্যাক্টরে স্ট্রিংগুলি ম্যাপিং করা অনেক সহজ সমাধান হবে। তাদের যদি বস্তুর প্রয়োজন না হয় তবে তাদের এগুলি থেকে মুক্তি দেওয়া উচিত, তবে আমি বাকি প্রোগ্রামটি দেখতে পাচ্ছি না, তাই সম্ভবত তারা বস্তু অন্য কোথাও অবজেক্ট হিসাবে বেশি ব্যবহৃত হয় ...?
হতাশ

@ ফ্রেস্ট্রেটেড উইথফোর্ডস ডিজাইনার তারা হতে পারে, তবে সেই পদ্ধতির সুযোগে এটি কেবল একটি দীর্ঘ প্রত্যাবর্তন করবে এবং তাত্ক্ষণিক বস্তুটি সুযোগের বাইরে চলে যাবে। একদিকে যেমন, এই কোডটি আরও ঘন ঘন বলা হয়ে থাকে তবে এর কোনও পার্শ্ব প্রতিক্রিয়া নেই frequently

এই উত্তরগুলির কোনওটিই মূল প্রোগ্রামের মতো একই সমাধান সরবরাহ হিসাবে বিবেচনা করা যায় না কারণ তারা ধারনাগুলির উপর নির্ভর করে যা বৈধ নয়। জাভা কোড: আপনি কীভাবে নিশ্চিত হন যে পদ্ধতিগুলি কেবলমাত্র একটি গুণক প্রয়োগ করে? পাইথন কোড: আপনি কীভাবে নিশ্চিত যে স্ট্রিংয়ে অঙ্কগুলি (যেমন "123.456s") ব্যতীত নেতৃস্থানীয় (বা মাঝের পয়েন্ট) অক্ষর ধারণ করার অনুমতি নেই।
mattnz

@ ম্যাট্টনজ - প্রদত্ত উদাহরণগুলির মধ্যে ভেরিয়েবলের নামগুলি আবার দেখুন। এটি স্পষ্ট যে ওপি একটি স্ট্রিং হিসাবে একটি সময় ইউনিট পাচ্ছে এবং তারপরে এটিকে অন্য ধরণের টাইম ইউনিটে রূপান্তর করতে হবে। সুতরাং এই উত্তরে প্রদত্ত উদাহরণগুলি সরাসরি ওপি'র ডোমেনের সাথে সম্পর্কিত। সেই দিকটি উপেক্ষা করে, উত্তরটি এখনও একটি জেনেরিক পদ্ধতির সরবরাহ করে যা কোনও অন্য ডোমেনের জন্য ব্যবহার করা যেতে পারে। এই উত্তরটি যে সমস্যাটি উপস্থাপিত হয়েছিল তা সমাধান করে না যা উপস্থাপন করা হতে পারে।

5
@ ম্যাট্টনজ - ১) ওপি কখনই তাদের উদাহরণে তা উল্লেখ করে না এবং পারে না। আপনি কীভাবে অনুমানগুলি অবৈধ তা জানেন? 2) সাধারণ পদ্ধতিটি এখনও কাজ করবে, সম্ভাব্যভাবে আরও জটিল রেজেক্সের প্রয়োজন। 3) উত্তরের বিষয়টি হ'ল চক্রবৃত্তীয় জটিলতা সমাধানের জন্য একটি ধারণামূলক পথ সরবরাহ করা, এবং প্রয়োজনীয় কোনও নির্দিষ্ট, সংকলনযোগ্য উত্তর নয়। ৪) যদিও এই উত্তরটি "জটিলতার বিষয়টি করে" এর বিস্তৃত দিকটিকে উপেক্ষা করে, কোডের বিকল্প ফর্ম দেখিয়ে পরোক্ষভাবে সমস্যার উত্তর দেয়।

3

যেহেতু আপনি return millisসেই ভয়ঙ্কর ifelseifelse শেষে যেহেতু , মনে মনে প্রথম জিনিসটি হ'ল যদি-ব্লকগুলির মধ্যে থেকে অবিলম্বে মানটি ফিরিয়ে দেওয়া হয়। এই পদ্ধতির গার্ড ক্লজ সহ নেস্টেড কন্ডিশনাল রিপ্লেস হিসাবে রিফ্যাক্টরিং প্যাটার্নগুলির তালিকাভুক্ত তালিকা অনুসরণ করা হয় ।

একটি পদ্ধতির শর্তাধীন আচরণ রয়েছে যা কার্যকর করার সাধারণ পথটি কী তা পরিষ্কার করে না

সমস্ত বিশেষ ক্ষেত্রে গার্ড ক্লজ ব্যবহার করুন

এটি আপনাকে অন্যের থেকে পরিত্রাণ পেতে, কোডটি সমতল করতে এবং সোনারকে আনন্দিত করতে সহায়তা করবে:

    if (sValue.endsWith("S")) {
        return new ExtractSecond(sValue).invoke();
    } // no need in else after return, code flattened

    if (sValue.endsWith("ms")) {
        return new ExtractMillisecond(sValue).invoke();
    }

    // and so on...
    return Long.parseLong(sValue); // forget millis, these aren't needed anymore

বিবেচনা করার মতো আর একটি বিষয় হ'ল ট্রাই-ক্যাচ ব্লকটি বাদ দেওয়া। এটি সাইক্লোমেটিক জটিলতাও কমিয়ে দেবে, তবে আমি কেন এটি সুপারিশ করার মূল কারণ হ'ল এই ব্লকটির সাথে কলার কোডের জন্য সংখ্যা বিন্যাসের ব্যতিক্রম থেকে আইনত পার্সড 0 পার্থক্য করার কোনও উপায় নেই।

যদি আপনি 200% নিশ্চিত না হন যে পার্স ত্রুটির জন্য 0 ফিরিয়ে দেওয়া কলার কোডের জন্য প্রয়োজনীয়, আপনি সেই ব্যতিক্রমটি আরও ভালভাবে প্রচার করতে পারেন এবং কলার কোডটি কীভাবে এটি মোকাবেলা করবেন তা সিদ্ধান্ত নিতে দিন। মৃত্যুদণ্ড কার্যকর করা বাতিল করা বা ইনপুট পাওয়ার জন্য পুনরায় চেষ্টা করা, বা 0 বা -1 বা কিছু যাই হোক না কেন কিছু ডিফল্ট মানটিতে ফিরতে হবে কিনা তা কলকারীর পক্ষে সাধারণত সিদ্ধান্ত নেওয়া আরও সুবিধাজনক।


আপনার কোড স্নিপেট উদাহরণের জন্য এক্সট্রাক্টআউট আমাকে অনুভব করে যে এক্সট্র্যাক্ট এক্সএক্সএক্স কার্যকারিতা অনুকূল থেকে অনেক দূরে ডিজাইন করা হয়েছে। আমি বাকী সমস্ত ক্লাসকে বাজি রেখে নির্দ্বিধায় একই পুনরাবৃত্তি করিparseDouble এবং substringএবং 60 এবং 1000 এর মত বার বার বার করি।

এর কারণ আপনি কিসের উপর নির্ভর করে কী করা দরকার তার সারাংশটি মিস করেছেন sValue- যথা, এটি স্ট্রিংয়ের শেষে থেকে কত অক্ষর কাটতে হবে এবং গুণক মানটি কী তা নির্ধারণ করে। আপনি যদি এই প্রয়োজনীয় বৈশিষ্ট্যগুলির চারপাশে আপনার "কোর" অবজেক্টটি ডিজাইন করেন তবে এটি নীচের মত দেখতে হবে:

private static class ParseHelper {
    // three things you need to know to parse:
    final String source;
    final int charsToCutAtEnd;
    final long multiplier;

    ParseHelper(String source, int charsToCutAtEnd, long multiplier) {
        this.source = source == null ? "0" : source; // let's handle null here
        this.charsToCutAtEnd = charsToCutAtEnd;
        this.multiplier = multiplier;
    }

    long invoke() {
        // NOTE consider Long.parseLong instead of Double.parseDouble here
        return (long) (Double.parseDouble(cutAtEnd()) * multiplier);
    }

    private String cutAtEnd() {
        if (charsToCutAtEnd == 0) {
            return source;
        }
        // write code that cuts 'charsToCutAtEnd' from the end of the 'source'
        throw new UnsupportedOperationException();
    }
}

এর পরে, আপনার এমন একটি কোডের দরকার আছে যা যদি পূরণ হয় তবে নির্দিষ্ট শর্তে উপরের অবজেক্টগুলিকে কনফিগার করে বা অন্যভাবে "বাইপাস" করে। এটি নিম্নলিখিত হিসাবে করা যেতে পারে:

private ParseHelper setupIfInSecond(ParseHelper original) {
    final String sValue = original.source;
    return sValue.endsWith("s") && !sValue.endsWith("ms")
            ? new ParseHelper(sValue, 1, 1000)
            :  original; // bypass
}

private ParseHelper setupIfMillisecond(ParseHelper original) {
    final String sValue = original.source;
    return sValue.endsWith("ms")
            ? new ParseHelper(sValue, 2, 1)
            : original; // bypass
}

// and so on...

উপরের বিল্ডিং ব্লকের উপর ভিত্তি করে , আপনার পদ্ধতির কোডটি নীচের মত দেখতে পারে:

public long parseTimeValue(String sValue) {

   return setupIfSecond(
           setupIfMillisecond(
           setupIfInSecond(
           setupIfInMinute(
           setupIfHour(
           setupIfDay(
           setupIfWeek(
           new ParseHelper(sValue, 0, 1))))))))
           .invoke();
}

আপনি দেখুন, কোনও জটিলতা বাকি নেই, পদ্ধতির অভ্যন্তরে কোনও কোঁকড়ানো ধনুর্বন্ধনী নেই ( সমতল কোডের ক্ষেত্রে আমার মূল ব্রুট ফোর্সের পরামর্শ মতো একাধিক আয় )। আপনি কেবল ক্রমানুসারে ইনপুটটি পরীক্ষা করে দেখুন এবং প্রসেসিংটি প্রয়োজনীয় হিসাবে সামঞ্জস্য করুন।


1

আপনি যদি সত্যই এটি রিফ্যাক্টর করতে চান তবে আপনি এরকম কিছু করতে পারেন:

// All of your Extract... classes will have to implement this interface!
public Interface TimeExtractor
{
    public long invoke();
}

private static class ExtractHour implements TimeExtractor
{
  private String sValue;


  /*Not sure what this was for - might not be necessary now
  public ExtractHour(String sValue)
  {
     this.sValue = sValue;
  }*/

  public long invoke(String s)
  {
     this.sValue = s;
     long millis;
     millis = (long) (Double.parseDouble(sValue.substring(0, sValue.length() - 1)) * 60 * 60 * 1000);
     return millis;
 }
}

private static HashMap<String, TimeExtractor> extractorMap= new HashMap<String, TimeExtractor>();

private void someInitMethod()
{
   ExtractHour eh = new ExtractorHour;
   extractorMap.add("H",eh);
   /*repeat for all extractors */
}

public static long parseTimeValue(String sValue)
{
    if (sValue == null)
    {
        return 0;
    }
    String key = extractKeyFromSValue(sValue);
    long millis;
    TimeExtractor extractor = extractorMap.get(key);
    if (extractor!=null)
    {
      try
      {
         millis= extractor.invoke(sValue);
      }
        catch (NumberFormatException e)
      {
          LOGGER.warn("Number format exception", e);
      }
    }
    else
       LOGGER.error("NO EXTRACTOR FOUND FOR "+key+", with sValue: "+sValue);

    return millis;
}

ধারণাটি হ'ল আপনার কাছে কীগুলির একটি মানচিত্র রয়েছে (আপনি কী "সর্বশেষে" কী ব্যবহার করেন সর্বদা) সেই মানচিত্রটি নির্দিষ্ট বস্তুগুলিতে যা আপনি চান প্রসেসিং করে।

এটি এখানে কিছুটা রুক্ষ তবে আমি আশা করি এটি যথেষ্ট পরিস্কার। আমি এর বিশদটি পূরণ করিনি extractKeyFromSValue()কারণ এই স্ট্রিংগুলি সঠিকভাবে কী করতে পারে তা কেবলমাত্র আমি জানি না। দেখে মনে হচ্ছে এটি সর্বশেষ 1 বা 2 অ-সংখ্যাসূচক অক্ষর (একটি রেজেক্স সম্ভবত এটি সহজেই যথেষ্ট পরিমাণে বের করতে পারে, সম্ভবত .*([a-zA-Z]{1,2})$এটি কাজ করবে) তবে আমি 100% নিশ্চিত নই ...


আসল উত্তর:

আপনি পরিবর্তন করতে পারে

else if (sValue.endsWith("H") || sValue.endsWith("h")) {

থেকে

else if (sValue.toUpper().endsWith("H")) {

এটি আপনাকে সামান্য কিছুটা সাশ্রয় করতে পারে, তবে সত্যি বলতে, আমি এটি সম্পর্কে খুব বেশি চিন্তা করব না। আমি আপনার সাথে একমত যে পদ্ধতিটি যেমন আছে তেমন রেখে দেওয়ার ক্ষেত্রে আমার খুব বেশি ক্ষতি হয় বলে আমি মনে করি না। "সোনার নিয়মগুলি মানার" পরিবর্তে "সোনার নির্দেশিকাগুলির নিকটে থাকার চেষ্টা করুন, যথাসম্ভব যথাসম্ভব"।

এই বিশ্লেষণ সরঞ্জামগুলির মধ্যে থাকা প্রতিটি নিয়ম মেনে চলার চেষ্টা করে আপনি নিজেকে ক্ষিপ্ত করে তুলতে পারেন, তবে আপনাকেও সিদ্ধান্ত নিতে হবে যে নিয়মগুলি আপনার প্রকল্পের জন্য অর্থবোধ করে কিনা এবং নির্দিষ্ট ক্ষেত্রে যেখানে রিফ্যাক্টরিংয়ের জন্য ব্যয় করা সময়টি উপযুক্ত নাও হতে পারে for ।


3
ব্যবহার খুব বেশি নয়, সোনার এখনও অভিযোগ করে। আমি মজাদার জন্য এটি চেষ্টা করার চেষ্টা করছি, কমপক্ষে একটি বা দুটি শিখতে দেয়। কোড যদিও মঞ্চে সরানো হয়।
asyncwait

@ সিনসয়েট: আহ, আমি ভেবেছিলাম আপনি সোনার থেকে এই রিপোর্টটি তার চেয়ে বেশি গুরুত্ব সহকারে নিচ্ছেন। হ্যাঁ, আমি প্রস্তাবিত পরিবর্তনটি কোনও বিশাল পার্থক্য তৈরি করবে না - আমি মনে করি না এটি আপনাকে 13 থেকে 10 পর্যন্ত নিয়ে যাবে, তবে কিছু সরঞ্জামে আমি এই ধরণের জিনিসটিকে কিছুটা লক্ষণীয় পার্থক্য করতে দেখেছি।
হতাশ

স্রেফ আরেকটি আইএফ শাখা যুক্ত করা সিসিকে +1 এ বাড়িয়েছে।
asyncwait

0

আপনি আপনার উপলব্ধ সমস্ত কেস সংরক্ষণ করার জন্য এনাম ব্যবহার বিবেচনা করতে পারেন এবং মিলের মানগুলির জন্য পূর্বাভাস দিতে পারেন। আপনার ফাংশনটি কেবল অপরিবর্তিত রাখার জন্য যথেষ্ট পঠনযোগ্য হওয়ার পূর্বে উল্লিখিত হিসাবে। এই মেট্রিকগুলি আপনাকে অন্য কোনও উপায়ে সাহায্য করার জন্য নয়।

//utility class for matching values
private static class ValueMatchingPredicate implements Predicate<String>{
    private final String[] suffixes;

    public ValueMatchingPredicate(String[] suffixes) {      
        this.suffixes = suffixes;
    }

    public boolean apply(String sValue) {
        if(sValue == null) return false;

        for (String suffix : suffixes) {
            if(sValue.endsWith(suffix)) return true;
        }

        return false;
    }

    public static Predicate<String> withSuffix(String... suffixes){         
        return new ValueMatchingPredicate(suffixes);
    }       
}

//enum containing all possible options
private static enum TimeValueExtractor {                
    SECOND(
        ValueMatchingPredicate.withSuffix("S"), 
        new Function<String, Long>(){ 
            public Long apply(String sValue) {  return new ExtractSecond(sValue).invoke(); }
        }),

    MILISECOND(
        ValueMatchingPredicate.withSuffix("ms"), 
        new Function<String, Long>(){
            public Long apply(String sValue) { return new ExtractMillisecond(sValue).invoke(); }
        }),

    IN_SECOND(
        ValueMatchingPredicate.withSuffix("s"),
        new Function<String, Long>(){
            public Long apply(String sValue) { return new ExtractInSecond(sValue).invoke(); }
        }),

    IN_MINUTE(
        ValueMatchingPredicate.withSuffix("m"),
        new Function<String, Long>(){
            public Long apply(String sValue) {  return new ExtractInMinute(sValue).invoke(); }
        }),

    HOUR(
        ValueMatchingPredicate.withSuffix("H", "h"),
        new Function<String, Long>(){
            public Long apply(String sValue) {  return new ExtractHour(sValue).invoke(); }
        }),

    DAY(
        ValueMatchingPredicate.withSuffix("d"),
        new Function<String, Long>(){
            public Long apply(String sValue) {  return new ExtractDay(sValue).invoke(); }
        }),

    WEEK(
        ValueMatchingPredicate.withSuffix("w"),
        new Function<String, Long>(){
            public Long apply(String sValue) {  return new ExtractWeek(sValue).invoke(); }
        });

    private final Predicate<String>      valueMatchingRule;
    private final Function<String, Long> extractorFunction;

    public static Long DEFAULT_VALUE = 0L;

    private TimeValueExtractor(Predicate<String> valueMatchingRule, Function<String, Long> extractorFunction) {
        this.valueMatchingRule = valueMatchingRule;
        this.extractorFunction = extractorFunction;
    }

    public boolean matchesValueSuffix(String sValue){
        return this.valueMatchingRule.apply(sValue);
    }

    public Long extractTimeValue(String sValue){
        return this.extractorFunction.apply(sValue);
    }

    public static Long extract(String sValue) throws NumberFormatException{
        TimeValueExtractor[] extractors = TimeValueExtractor.values();

        for (TimeValueExtractor timeValueExtractor : extractors) {
            if(timeValueExtractor.matchesValueSuffix(sValue)){
                return timeValueExtractor.extractTimeValue(sValue);
            }
        }

        return DEFAULT_VALUE;
    }
}

//your function
public static long parseTimeValue(String sValue){
    try{
        return TimeValueExtractor.extract(sValue);
    } catch (NumberFormatException e) {
        //LOGGER.warn("Number format exception", e);
        return TimeValueExtractor.DEFAULT_VALUE;
    }
}

0

আপনার মন্তব্য সম্পর্কিত:

নীচের লাইন - সোনার (বা হাফ বেকড প্রজেক্ট ম্যানেজার) স্বার্থে ওভার ইঞ্জিনিয়ারকে সিসির বিষয়ে অভিযোগ করবেন না। প্রকল্পের জন্য কেবল এক পয়সা মূল্যবান জিনিসই করুন।

বিবেচনা করার জন্য অন্য বিকল্পটি হ'ল এই জাতীয় পরিস্থিতির জন্য আপনার দলের কোডিং মান পরিবর্তন করা। সামান্য প্রশাসনের ব্যবস্থা করতে এবং সংক্ষিপ্ত-পরিস্থিতি এড়াতে সম্ভবত আপনি কোনও ধরণের দল-ভোট যোগ করতে পারেন।

তবে পরিস্থিতিগুলির প্রতিক্রিয়ায় দলের মান পরিবর্তন করা মানসিকভাবে সঠিক দৃষ্টিভঙ্গি সহ একটি ভাল দলের লক্ষণ। কোড লেখার পথে না গিয়ে দলকে সহায়তা করার জন্য মানক রয়েছে।


0

সত্যি কথা বলতে, উপরের সমস্ত প্রযুক্তিগত প্রতিক্রিয়াগুলি হাতের কাজটির জন্য মারাত্মক জটিল বলে মনে হচ্ছে। যেমনটি ইতিমধ্যে লেখা ছিল, কোড নিজেই পরিষ্কার এবং ভাল, তাই জটিলতা কাউন্টারকে সন্তুষ্ট করার জন্য আমি ক্ষুদ্রতম পরিবর্তনের বিকল্পটি বেছে নেব। নিম্নলিখিত চুল্লি সম্পর্কে:

public static long parseTimeValue(String sValue) {

    if (sValue == null) {
        return 0;
    }

    try {
        return getMillis(sValue);
    } catch (NumberFormatException e) {
        LOGGER.warn("Number format exception", e);
    }

    return 0;
}

private static long getMillis(String sValue) {
    if (sValue.endsWith("S")) {
        return new ExtractSecond(sValue).invoke();
    } else if (sValue.endsWith("ms")) {
        return new ExtractMillisecond(sValue).invoke();
    } else if (sValue.endsWith("s")) {
        return new ExtractInSecond(sValue).invoke();
    } else if (sValue.endsWith("m")) {
        return new ExtractInMinute(sValue).invoke();
    } else if (sValue.endsWith("H") || sValue.endsWith("h")) {
        return new ExtractHour(sValue).invoke();
    } else if (sValue.endsWith("d")) {
        return new ExtractDay(sValue).invoke();
    } else if (sValue.endsWith("w")) {
        return new ExtractWeek(sValue).invoke();
    } else {
        return Long.parseLong(sValue);
    }
}

যদি আমি সঠিকভাবে গণনা করছি, উত্তোলিত ফাংশনটির 9 টির জটিলতা হওয়া উচিত, যা এখনও প্রয়োজনীয়তাগুলি পাস করে। এবং এটি মূলত আগের মত একই কোড , যা একটি ভাল জিনিস, যেহেতু কোডটি শুরু করা ভাল ছিল।

এছাড়াও, ক্লিন কোডের পাঠকরা এই সত্যটি উপভোগ করতে পারেন যে শীর্ষ স্তরের পদ্ধতিটি এখন সহজ এবং সংক্ষিপ্ত, যখন নিষ্কাশিত একটি বিবরণ নিয়ে আলোচনা করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.