অবদানকারীদের জন্য AOSP জাভা কোড শৈলী

এই পৃষ্ঠার কোড শৈলীগুলি Android ওপেন সোর্স প্রজেক্টে (AOSP) জাভা কোড অবদান রাখার জন্য কঠোর নিয়ম। Android প্ল্যাটফর্মে অবদানগুলি যেগুলি এই নিয়মগুলি মেনে চলে না সেগুলি সাধারণত গৃহীত হয় না ৷ আমরা স্বীকার করি যে সমস্ত বিদ্যমান কোড এই নিয়মগুলি অনুসরণ করে না, তবে আমরা আশা করি যে সমস্ত নতুন কোড মেনে চলবে। আরও অন্তর্ভুক্ত ইকোসিস্টেমের জন্য ব্যবহার এবং এড়ানোর জন্য পরিভাষার উদাহরণের জন্য কোডিং দেখুন।

অটল থাক

সবচেয়ে সহজ নিয়মগুলির মধ্যে একটি হল BE CONSISTENT। আপনি যদি কোড সম্পাদনা করেন, তবে আশেপাশের কোডটি দেখতে এবং এর শৈলী নির্ধারণ করতে কয়েক মিনিট সময় নিন। যদি কোডটি if ক্লজের চারপাশে স্পেস ব্যবহার করে তবে আপনারও উচিত। যদি কোড মন্তব্যে তাদের চারপাশে তারার ছোট বাক্স থাকে, তবে আপনার মন্তব্যগুলিতেও তাদের চারপাশে তারার ছোট বাক্স রয়েছে।

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

জাভা ভাষার নিয়ম

অ্যান্ড্রয়েড নীচে বর্ণিত অতিরিক্ত নিয়মগুলির সাথে স্ট্যান্ডার্ড জাভা কোডিং নিয়মাবলী অনুসরণ করে৷

ব্যতিক্রম উপেক্ষা করবেন না

এটি এমন কোড লিখতে প্রলুব্ধ হতে পারে যা একটি ব্যতিক্রম উপেক্ষা করে, যেমন:

  void setServerPort(String value) {
      try {
          serverPort = Integer.parseInt(value);
      } catch (NumberFormatException e) { }
  }

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

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

গ্রহণযোগ্য বিকল্প (পছন্দ অনুসারে) হল:

  • আপনার পদ্ধতির কলার পর্যন্ত ব্যতিক্রমটি নিক্ষেপ করুন।
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • একটি নতুন ব্যতিক্রম নিক্ষেপ করুন যা আপনার বিমূর্ততার স্তরের জন্য উপযুক্ত।
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • ত্রুটিটি সুন্দরভাবে পরিচালনা করুন এবং catch {} ব্লকে একটি উপযুক্ত মান প্রতিস্থাপন করুন।
      /** Set port. If value is not a valid number, 80 is substituted. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            serverPort = 80;  // default port for server
        }
      }
    
  • ব্যতিক্রমটি ধরুন এবং RuntimeException এর একটি নতুন উদাহরণ নিক্ষেপ করুন। এটি বিপজ্জনক, তাই এটি কেবল তখনই করুন যদি আপনি ইতিবাচক হন যে যদি এই ত্রুটিটি ঘটে, তাহলে সঠিক জিনিসটি ক্র্যাশ হয়৷
      /** Set port. If value is not a valid number, die. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("port " + value " is invalid, ", e);
        }
      }
    
  • শেষ অবলম্বন হিসাবে, আপনি যদি নিশ্চিত হন যে ব্যতিক্রম উপেক্ষা করা উপযুক্ত তবে আপনি এটি উপেক্ষা করতে পারেন, তবে আপনাকে অবশ্যই একটি ভাল কারণ সহ মন্তব্য করতে হবে।
    /** If value is not a valid number, original port number is used. */
    
    void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            // Method is documented to just ignore invalid user input.
            // serverPort will just be unchanged.
        }
    }
    

জেনেরিক ব্যতিক্রম ধরবেন না

ব্যতিক্রমগুলি ধরার সময় অলস হতে প্রলুব্ধ হতে পারে এবং এরকম কিছু করতে পারে:

  try {
      someComplicatedIOFunction();        // may throw IOException
      someComplicatedParsingFunction();   // may throw ParsingException
      someComplicatedSecurityFunction();  // may throw SecurityException
      // phew, made it all the way
  } catch (Exception e) {                 // I'll just catch all exceptions
      handleError();                      // with one generic handler!
  }

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

এই নিয়মের বিরল ব্যতিক্রম হল টেস্ট কোড এবং টপ-লেভেল কোড যেখানে আপনি সব ধরনের ত্রুটি ধরতে চান (একটি UI এ দেখানো থেকে বিরত রাখতে বা ব্যাচের কাজ চালিয়ে যেতে)। এই ক্ষেত্রে, আপনি জেনেরিক Exception (বা Throwable ) ধরতে পারেন এবং ত্রুটিটি যথাযথভাবে পরিচালনা করতে পারেন। যদিও এটি করার আগে সাবধানে চিন্তা করুন এবং এই প্রসঙ্গে কেন এটি নিরাপদ তা ব্যাখ্যা করে মন্তব্য করুন।

সাধারণ ব্যতিক্রম ধরার বিকল্প:

  • মাল্টি-ক্যাচ ব্লকের অংশ হিসাবে প্রতিটি ব্যতিক্রম আলাদাভাবে ধরুন, উদাহরণস্বরূপ:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • একাধিক ট্রাই ব্লক সহ আরও সূক্ষ্ম ত্রুটি পরিচালনা করতে আপনার কোড রিফ্যাক্টর করুন। পার্সিং থেকে IO কে বিভক্ত করুন এবং প্রতিটি ক্ষেত্রে আলাদাভাবে ত্রুটিগুলি পরিচালনা করুন।
  • ব্যতিক্রমটি পুনরুদ্ধার করুন। অনেক সময় আপনাকে এই স্তরে ব্যতিক্রম ধরতে হবে না, শুধু পদ্ধতিটিকে এটি নিক্ষেপ করতে দিন।

মনে রাখবেন যে ব্যতিক্রম আপনার বন্ধু! যখন কম্পাইলার অভিযোগ করে যে আপনি একটি ব্যতিক্রম ধরছেন না, তখন ঘাবড়ে যাবেন না। হাসি! কম্পাইলারটি আপনার কোডে রানটাইম সমস্যাগুলি ধরতে আপনার জন্য সহজ করে দিয়েছে।

ফাইনালিজার ব্যবহার করবেন না

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

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

সম্পূর্ণরূপে যোগ্য আমদানি

আপনি যখন প্যাকেজ foo থেকে ক্লাস Bar ব্যবহার করতে চান, তখন এটি আমদানি করার দুটি সম্ভাব্য উপায় রয়েছে:

  • import foo.*;

    সম্ভাব্য আমদানি বিবৃতি সংখ্যা হ্রাস.

  • import foo.Bar;

    কোন ক্লাস ব্যবহার করা হয় তা স্পষ্ট করে তোলে এবং কোডটি রক্ষণাবেক্ষণকারীদের জন্য আরও পাঠযোগ্য।

import foo.Bar; সমস্ত অ্যান্ড্রয়েড কোড আমদানি করার জন্য। জাভা স্ট্যান্ডার্ড লাইব্রেরি ( java.util.* , java.io.* , ইত্যাদি) এবং ইউনিট টেস্ট কোড ( junit.framework.* ) এর জন্য একটি স্পষ্ট ব্যতিক্রম করা হয়েছে।

জাভা লাইব্রেরির নিয়ম

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

জাভা স্টাইলের নিয়ম

Javadoc স্ট্যান্ডার্ড মন্তব্য ব্যবহার করুন

প্রতিটি ফাইলের উপরে একটি কপিরাইট বিবৃতি থাকা উচিত, তারপরে প্যাকেজ এবং আমদানি বিবৃতি (প্রতিটি ব্লক একটি ফাঁকা লাইন দ্বারা পৃথক করা হয়েছে), এবং অবশেষে ক্লাস বা ইন্টারফেস ঘোষণা। Javadoc মন্তব্যে, ক্লাস বা ইন্টারফেস কী করে তা বর্ণনা করুন।

/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

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

উদাহরণ

/** Returns the correctly rounded positive square root of a double value. */

static double sqrt(double a) {
    ...
}

বা

/**
 * Constructs a new String by converting the specified array of
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

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

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

সংক্ষিপ্ত পদ্ধতি লিখুন

যখন সম্ভব হয়, পদ্ধতি ছোট এবং ফোকাস রাখুন. আমরা স্বীকার করি যে দীর্ঘ পদ্ধতিগুলি কখনও কখনও উপযুক্ত, তাই পদ্ধতির দৈর্ঘ্যের উপর কোন কঠিন সীমা স্থাপন করা হয় না। যদি একটি পদ্ধতি 40 লাইন বা তার বেশি হয়, তাহলে প্রোগ্রামের কাঠামোর ক্ষতি না করে এটি ভেঙে ফেলা যায় কিনা তা নিয়ে ভাবুন।

মানক স্থানে ক্ষেত্র সংজ্ঞায়িত করুন

ফাইলের শীর্ষে বা তাদের ব্যবহার করা পদ্ধতির ঠিক আগে ক্ষেত্রগুলিকে সংজ্ঞায়িত করুন।

পরিবর্তনশীল সুযোগ সীমিত করুন

স্থানীয় ভেরিয়েবলের সুযোগ ন্যূনতম রাখুন। এটি আপনার কোডের পঠনযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা বাড়ায় এবং ত্রুটির সম্ভাবনা হ্রাস করে। অভ্যন্তরীণ ব্লকে প্রতিটি ভেরিয়েবল ঘোষণা করুন যা ভেরিয়েবলের সমস্ত ব্যবহারকে আবদ্ধ করে।

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

ব্যতিক্রম হল ট্রাই-ক্যাচ স্টেটমেন্ট। যদি একটি ভেরিয়েবলকে একটি পদ্ধতির রিটার্ন মান দিয়ে আরম্ভ করা হয় যা একটি চেক করা ব্যতিক্রম নিক্ষেপ করে, তবে এটি একটি চেষ্টা ব্লকের মধ্যে আরম্ভ করা আবশ্যক। যদি মানটি অবশ্যই ট্রাই ব্লকের বাইরে ব্যবহার করা উচিত, তবে এটি অবশ্যই ট্রাই ব্লকের আগে ঘোষণা করতে হবে, যেখানে এটি এখনও সংবেদনশীলভাবে আরম্ভ করা যাবে না:

// Instantiate class cl, which represents some sort of Set

Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set
s.addAll(Arrays.asList(args));

যাইহোক, আপনি একটি পদ্ধতিতে ট্রাই-ক্যাচ ব্লককে এনক্যাপসুলেট করে এই কেসটি এড়াতে পারেন:

Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

বিবৃতিতে লুপ ভেরিয়েবল ঘোষণা করুন যদি না অন্যথায় করার বাধ্যতামূলক কারণ থাকে:

for (int i = 0; i < n; i++) {
    doSomething(i);
}

এবং

for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

অর্ডার আমদানি বিবৃতি

আমদানি বিবৃতিগুলির ক্রম হল:

  1. অ্যান্ড্রয়েড আমদানি
  2. তৃতীয় পক্ষ থেকে আমদানি ( com , junit , net , org )
  3. java এবং javax

IDE সেটিংসের সাথে হুবহু মেলে, আমদানি হওয়া উচিত:

  • প্রতিটি গ্রুপিংয়ের মধ্যে বর্ণানুক্রমিক, ছোট হাতের অক্ষরের আগে বড় অক্ষর সহ (উদাহরণস্বরূপ, a এর আগে Z)
  • প্রতিটি প্রধান গ্রুপিং ( android , com , junit , net , org , java , javax ) এর মধ্যে একটি ফাঁকা লাইন দ্বারা পৃথক করা হয়েছে

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

আমরা এই শৈলীটি এমনভাবে বেছে নিয়েছি:

  • লোকেরা প্রথমে দেখতে চায় যে আমদানিগুলি শীর্ষে থাকে ( android )।
  • মানুষ যে আমদানি দেখতে চায় তা অন্তত নিচের দিকে থাকে ( java )।
  • মানুষ সহজে শৈলী অনুসরণ করতে পারেন.
  • IDE শৈলী অনুসরণ করতে পারেন.

নিয়মিত আমদানির মতো একইভাবে আদেশকৃত অন্যান্য আমদানির উপরে স্ট্যাটিক আমদানি রাখুন।

ইন্ডেন্টেশনের জন্য স্পেস ব্যবহার করুন

আমরা ব্লকের জন্য চারটি (4) স্পেস ইন্ডেন্ট ব্যবহার করি এবং কখনও ট্যাব করি না। সন্দেহ হলে, পার্শ্ববর্তী কোডের সাথে সামঞ্জস্যপূর্ণ হন।

আমরা ফাংশন কল এবং অ্যাসাইনমেন্ট সহ লাইন মোড়ানোর জন্য আট (8) স্পেস ইন্ডেন্ট ব্যবহার করি।

প্রস্তাবিত

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);

সুপারিশ করা হয় না

Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);

ক্ষেত্রের নামকরণের নিয়ম অনুসরণ করুন

  • অ-সর্বজনীন, নন-স্ট্যাটিক ক্ষেত্রের নাম m দিয়ে শুরু হয়।
  • স্ট্যাটিক ক্ষেত্রের নাম s দিয়ে শুরু হয়।
  • অন্যান্য ক্ষেত্রগুলি একটি ছোট হাতের অক্ষর দিয়ে শুরু হয়।
  • স্থির চূড়ান্ত ক্ষেত্র (ধ্রুবক, গভীরভাবে অপরিবর্তনীয়) হল ALL_CAPS_WITH_UNDERSCORES

উদাহরণ স্বরূপ:

public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

স্ট্যান্ডার্ড ব্রেস শৈলী ব্যবহার করুন

তাদের সামনে কোডের মতো একই লাইনে ধনুর্বন্ধনী রাখুন, তাদের নিজস্ব লাইনে নয়:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

আমরা একটি শর্তসাপেক্ষ জন্য বিবৃতি চারপাশে বন্ধনী প্রয়োজন. ব্যতিক্রম: যদি সম্পূর্ণ শর্তসাপেক্ষ (শর্ত এবং শরীর) এক লাইনে মাপসই হয়, তাহলে আপনি এটিকে এক লাইনে রাখতে পারেন (কিন্তু বাধ্য নন)। উদাহরণস্বরূপ, এটি গ্রহণযোগ্য:

if (condition) {
    body();
}

এবং এটি গ্রহণযোগ্য:

if (condition) body();

কিন্তু এটি গ্রহণযোগ্য নয়:

if (condition)
    body();  // bad!

লাইনের দৈর্ঘ্য সীমিত করুন

আপনার কোডের পাঠ্যের প্রতিটি লাইন সর্বাধিক 100 অক্ষর দীর্ঘ হওয়া উচিত। যদিও অনেক আলোচনা এই নিয়মটিকে ঘিরে রয়েছে, সিদ্ধান্তটি রয়ে গেছে যে 100টি অক্ষর সর্বাধিক নিম্নলিখিত ব্যতিক্রমগুলির সাথে :

  • যদি একটি মন্তব্য লাইনে একটি উদাহরণ কমান্ড বা 100 অক্ষরের চেয়ে দীর্ঘ একটি আক্ষরিক URL থাকে, তাহলে কাটা এবং পেস্ট করার সুবিধার জন্য সেই লাইনটি 100 অক্ষরের বেশি হতে পারে।
  • আমদানি লাইন সীমা অতিক্রম করতে পারে কারণ মানুষ খুব কমই তাদের দেখতে পায় (এটি টুল লেখাকেও সহজ করে)।

স্ট্যান্ডার্ড জাভা টীকা ব্যবহার করুন

একই ভাষার উপাদানের জন্য টীকাগুলি অন্যান্য মডিফায়ারের আগে থাকা উচিত। সহজ মার্কার টীকা (উদাহরণস্বরূপ, @Override ) ভাষা উপাদানের সাথে একই লাইনে তালিকাভুক্ত করা যেতে পারে। যদি একাধিক টীকা বা প্যারামিটারাইজড টীকা থাকে, সেগুলিকে বর্ণানুক্রমিক ক্রমে এক-প্রতি-লাইনে তালিকাভুক্ত করুন।

জাভাতে তিনটি পূর্বনির্ধারিত টীকাগুলির জন্য অ্যান্ড্রয়েড স্ট্যান্ডার্ড অনুশীলনগুলি হল:

  • যখনই টীকা করা উপাদানের ব্যবহার নিরুৎসাহিত করা হয় তখনই @Deprecated টীকা ব্যবহার করুন। আপনি যদি @Deprecated টীকা ব্যবহার করেন, তাহলে আপনার অবশ্যই একটি @deprecated Javadoc ট্যাগ থাকতে হবে এবং এটি একটি বিকল্প বাস্তবায়নের নাম দিতে হবে। উপরন্তু, মনে রাখবেন যে একটি @Deprecated পদ্ধতি এখনও কাজ করার কথা । আপনি যদি পুরানো কোড দেখেন যেটিতে @deprecated Javadoc ট্যাগ আছে, তাহলে @Deprecated টীকা যোগ করুন।
  • যখনই কোনো পদ্ধতি সুপারক্লাস থেকে ঘোষণা বা বাস্তবায়নকে ওভাররাইড করে তখন @Override টীকা ব্যবহার করুন। উদাহরণস্বরূপ, আপনি যদি @inheritdocs Javadoc ট্যাগ ব্যবহার করেন এবং একটি ক্লাস থেকে উদ্ভূত হন (কোন ইন্টারফেস নয়), তাহলে আপনাকে অবশ্যই টীকা দিতে হবে যে পদ্ধতিটি অভিভাবক শ্রেণীর পদ্ধতিকে ওভাররাইড করে।
  • @SuppressWarnings টীকাটি শুধুমাত্র এমন পরিস্থিতিতে ব্যবহার করুন যেখানে সতর্কতা দূর করা অসম্ভব। যদি কোনো সতর্কবার্তা এই "নির্মূল করা অসম্ভব" পরীক্ষায় উত্তীর্ণ হয়, তাহলে @SuppressWarnings টীকাটি ব্যবহার করতে হবে , যাতে নিশ্চিত করা যায় যে সমস্ত সতর্কতা কোডে প্রকৃত সমস্যাগুলি প্রতিফলিত করে।

    যখন একটি @SuppressWarnings টীকা প্রয়োজন হয়, তখন এটি একটি TODO মন্তব্যের সাথে প্রিফিক্স করা আবশ্যক যা "নির্মূল করা অসম্ভব" শর্তটি ব্যাখ্যা করে। এটি সাধারণত একটি আপত্তিকর শ্রেণী চিহ্নিত করে যার একটি বিশ্রী ইন্টারফেস রয়েছে। উদাহরণ স্বরূপ:

    // TODO: The third-party class com.third.useful.Utility.rotate() needs generics
    @SuppressWarnings("generic-cast")
    List<String> blix = Utility.rotate(blax);
    

    যখন একটি @SuppressWarnings টীকা প্রয়োজন হয়, যেখানে টীকাটি প্রযোজ্য হয় সেখানে সফ্টওয়্যার উপাদানগুলিকে আলাদা করতে কোডটিকে রিফ্যাক্টর করুন৷

সংক্ষিপ্ত শব্দগুলিকে শব্দ হিসাবে বিবেচনা করুন

নামকরণের ভেরিয়েবল, পদ্ধতি এবং শ্রেণীতে নামগুলিকে আরও পঠনযোগ্য করতে শব্দ হিসাবে সংক্ষিপ্ত শব্দ এবং সংক্ষিপ্ত রূপগুলি ব্যবহার করুন:

ভাল খারাপ
XmlHttp অনুরোধ XMLHTTPR অনুরোধ
GetCustomerId getCustomerID
ক্লাস এইচটিএমএল ক্লাস এইচটিএমএল
স্ট্রিং ইউআরএল স্ট্রিং URL
দীর্ঘ আইডি দীর্ঘ আইডি

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

TODO মন্তব্য ব্যবহার করুন

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

// TODO: Remove this code after the UrlTable2 has been checked in.

এবং

// TODO: Change this to use a flag instead of a constant.

যদি আপনার TODO ফর্মের হয় "ভবিষ্যত তারিখে কিছু করুন" নিশ্চিত করুন যে আপনি হয় একটি নির্দিষ্ট তারিখ অন্তর্ভুক্ত করেছেন ("নভেম্বর 2005 এর মধ্যে ঠিক করুন") বা একটি নির্দিষ্ট ইভেন্ট ("সকল প্রোডাকশন মিক্সার প্রোটোকল V7 বোঝার পরে এই কোডটি সরান।" )

সংযতভাবে লগ করুন

লগিং করা আবশ্যক হলেও, এটি কার্যক্ষমতার উপর নেতিবাচক প্রভাব ফেলে এবং যুক্তিসঙ্গতভাবে সংক্ষিপ্ত না রাখলে এর উপযোগিতা হারায়। লগিং সুবিধা পাঁচটি বিভিন্ন স্তরের লগিং প্রদান করে:

  • ERROR : যখন মারাত্মক কিছু ঘটে থাকে তখন ব্যবহার করুন, অর্থাৎ, কিছু ব্যবহারকারীর দৃশ্যমান পরিণতি হবে এবং কিছু ডেটা মুছে ফেলা, অ্যাপ আনইনস্টল করা, ডেটা পার্টিশন মুছে ফেলা, বা পুরো ডিভাইসটি রিফ্ল্যাশ না করে (বা আরও খারাপ) পুনরুদ্ধার করা যাবে না। এই স্তর সবসময় লগ করা হয়. যে সমস্যাগুলি ERROR স্তরে কিছু লগিংকে ন্যায্যতা দেয় সেগুলি একটি পরিসংখ্যান সংগ্রহকারী সার্ভারে রিপোর্ট করা ভাল প্রার্থী৷
  • WARNING : যখন কিছু গুরুতর এবং অপ্রত্যাশিত ঘটে তখন ব্যবহার করুন, অর্থাৎ, এমন কিছু যা ব্যবহারকারীর দৃশ্যমান পরিণতি হবে কিন্তু কিছু সুস্পষ্ট ক্রিয়া সম্পাদন করে ডেটা ক্ষতি ছাড়াই পুনরুদ্ধারযোগ্য হতে পারে, অপেক্ষা করা বা পুনরায় ডাউনলোড করা পর্যন্ত একটি অ্যাপ রিস্টার্ট করা থেকে শুরু করে একটি অ্যাপের একটি নতুন সংস্করণ বা ডিভাইস রিবুট করা। এই স্তর সবসময় লগ করা হয়. WARNING স্তরে লগিংকে ন্যায়সঙ্গত করে এমন সমস্যাগুলি পরিসংখ্যান সংগ্রহকারী সার্ভারে রিপোর্ট করার জন্যও বিবেচনা করা যেতে পারে।
  • INFORMATIVE : মনে রাখবেন যে আকর্ষণীয় কিছু ঘটেছে, অর্থাৎ, যখন এমন একটি পরিস্থিতি সনাক্ত করা হয় যা ব্যাপক প্রভাব ফেলতে পারে, যদিও এটি অগত্যা একটি ত্রুটি নয়। এই ধরনের শর্ত শুধুমাত্র একটি মডিউল দ্বারা লগ করা উচিত যেটি বিশ্বাস করে যে এটি সেই ডোমেনে সবচেয়ে বেশি প্রামাণিক (অনুমোদিত উপাদানগুলির দ্বারা ডুপ্লিকেট লগিং এড়াতে)। এই স্তর সবসময় লগ করা হয়.
  • DEBUG : ডিভাইসে কী ঘটছে তা আরও নোট করতে ব্যবহার করুন যা অপ্রত্যাশিত আচরণগুলি তদন্ত এবং ডিবাগ করার জন্য প্রাসঙ্গিক হতে পারে। আপনার উপাদানের সাথে কী ঘটছে সে সম্পর্কে যথেষ্ট তথ্য সংগ্রহ করার জন্য শুধুমাত্র যা প্রয়োজন তা লগ করুন। যদি আপনার ডিবাগ লগগুলি লগে আধিপত্য বিস্তার করে, তাহলে আপনার ভার্বোস লগিং ব্যবহার করা উচিত।

    এমনকি রিলিজ বিল্ডগুলিতেও এই স্তরটি লগ করা হয়, এবং একটি if (LOCAL_LOG) বা if LOCAL_LOGD) ব্লক দ্বারা বেষ্টিত থাকা প্রয়োজন, যেখানে LOCAL_LOG[D] আপনার ক্লাস বা সাবকম্পোনেন্টে সংজ্ঞায়িত করা হয়েছে, যাতে এই ধরনের সমস্ত লগিং অক্ষম করার সম্ভাবনা থাকে . অতএব, একটি if (LOCAL_LOG) ব্লকে কোনও সক্রিয় যুক্তি থাকতে হবে না। লগের জন্য সমস্ত স্ট্রিং বিল্ডিংও if (LOCAL_LOG) ব্লকের ভিতরে স্থাপন করা দরকার। লগিং কলটিকে মেথড কলে রিফ্যাক্টর করবেন না যদি এটি স্ট্রিং বিল্ডিংটি if (LOCAL_LOG) ব্লকের বাইরে ঘটতে পারে।

    কিছু কোড আছে যা এখনও বলে if (localLOGV) । এটিও গ্রহণযোগ্য বলে বিবেচিত হয়, যদিও নামটি মানহীন।

  • VERBOSE : অন্য সবকিছুর জন্য ব্যবহার করুন। এই স্তরটি শুধুমাত্র ডিবাগ বিল্ডগুলিতে লগ করা হয়েছে এবং একটি if (LOCAL_LOGV) ব্লক (বা সমতুল্য) দ্বারা বেষ্টিত হওয়া উচিত যাতে এটি ডিফল্টরূপে কম্পাইল করা যায়। যেকোনো স্ট্রিং বিল্ডিং রিলিজ বিল্ড থেকে ছিনিয়ে নেওয়া হয় এবং if (LOCAL_LOGV) ব্লকের ভিতরে উপস্থিত হওয়া প্রয়োজন।

মন্তব্য

  • একটি প্রদত্ত মডিউলের মধ্যে, VERBOSE স্তরের ব্যতীত, সম্ভব হলে একটি ত্রুটি শুধুমাত্র একবার রিপোর্ট করা উচিত৷ একটি মডিউলের মধ্যে ফাংশন কলের একটি একক চেইনের মধ্যে, শুধুমাত্র সবচেয়ে ভিতরের ফাংশনটি ত্রুটিটি ফেরত দেবে এবং একই মডিউলে কলকারীদের শুধুমাত্র কিছু লগিং যোগ করা উচিত যদি এটি উল্লেখযোগ্যভাবে সমস্যাটিকে আলাদা করতে সহায়তা করে।
  • মডিউলের একটি শৃঙ্খলে, VERBOSE স্তরের ব্যতীত, যখন একটি নিম্ন-স্তরের মডিউল একটি উচ্চ-স্তরের মডিউল থেকে আসা অবৈধ ডেটা শনাক্ত করে, তখন নিম্ন-স্তরের মডিউলটি শুধুমাত্র এই পরিস্থিতিটিকে DEBUG লগে লগ করা উচিত, এবং শুধুমাত্র যদি লগিং প্রদান করে। তথ্য যা অন্যথায় কলারের কাছে উপলব্ধ নয়। বিশেষ করে, এমন পরিস্থিতিতে লগ করার কোন প্রয়োজন নেই যেখানে একটি ব্যতিক্রম নিক্ষেপ করা হয় (ব্যতিক্রমটিতে সমস্ত প্রাসঙ্গিক তথ্য থাকা উচিত), বা যেখানে শুধুমাত্র লগ করা তথ্যটি একটি ত্রুটি কোডে রয়েছে। ফ্রেমওয়ার্ক এবং অ্যাপের মধ্যে মিথস্ক্রিয়ায় এটি বিশেষভাবে গুরুত্বপূর্ণ, এবং ফ্রেমওয়ার্ক দ্বারা সঠিকভাবে পরিচালনা করা তৃতীয়-পক্ষের অ্যাপগুলির কারণে সৃষ্ট শর্তগুলি DEBUG স্তরের চেয়ে বেশি লগিং ট্রিগার করবে না। শুধুমাত্র এমন পরিস্থিতিতে যা INFORMATIVE স্তরে বা উচ্চতর লগিংকে ট্রিগার করবে তা হল যখন একটি মডিউল বা অ্যাপ তার নিজের স্তরে একটি ত্রুটি সনাক্ত করে বা নিম্ন স্তর থেকে আসে।
  • যখন একটি শর্ত যা সাধারণত কিছু লগিংকে ন্যায্যতা দেয় তা অনেকবার ঘটতে পারে, তখন একই (বা খুব অনুরূপ) তথ্যের অনেকগুলি অনুলিপি সহ লগগুলিকে উপচে পড়া রোধ করতে কিছু হার-সীমিত প্রক্রিয়া প্রয়োগ করা একটি ভাল ধারণা হতে পারে।
  • নেটওয়ার্ক সংযোগের ক্ষতি সাধারণ হিসাবে বিবেচিত হয় এবং সম্পূর্ণরূপে প্রত্যাশিত, এবং অনাকাঙ্ক্ষিতভাবে লগ করা উচিত নয়। নেটওয়ার্ক কানেক্টিভিটির ক্ষতি যা একটি অ্যাপের মধ্যে পরিণতি রয়েছে তা DEBUG বা VERBOSE স্তরে লগ ইন করা উচিত (পরিণামগুলি যথেষ্ট গুরুতর এবং রিলিজ বিল্ডে লগ ইন করার জন্য যথেষ্ট অপ্রত্যাশিত কিনা তার উপর নির্ভর করে)৷
  • তৃতীয় পক্ষের অ্যাপগুলির পক্ষে বা তার পক্ষে অ্যাক্সেসযোগ্য একটি ফাইল সিস্টেমে একটি সম্পূর্ণ ফাইল সিস্টেম থাকা তথ্যের চেয়ে উচ্চ স্তরে লগ ইন করা উচিত নয়৷
  • কোনো অবিশ্বস্ত উৎস থেকে আসা অবৈধ ডেটা (শেয়ার করা স্টোরেজে থাকা কোনো ফাইল বা কোনো নেটওয়ার্ক সংযোগের মাধ্যমে আসা ডেটা সহ) প্রত্যাশিত বলে বিবেচিত হয় এবং যখন এটি অবৈধ বলে শনাক্ত হয় (এবং তারপরেও লগিং করা হয়) তখন DEBUG এর চেয়ে বেশি স্তরে কোনো লগিং ট্রিগার করা উচিত নয় যতটা সম্ভব সীমিত হওয়া উচিত)।
  • যখন String অবজেক্টে ব্যবহার করা হয়, তখন + অপারেটর ডিফল্ট বাফার সাইজ (16 অক্ষর) এবং সম্ভাব্য অন্যান্য অস্থায়ী String অবজেক্ট সহ একটি StringBuilder ইন্সট্যান্স তৈরি করে। তাই স্পষ্টভাবে StringBuilder অবজেক্ট তৈরি করা ডিফল্ট + অপারেটরের উপর নির্ভর করার চেয়ে বেশি ব্যয়বহুল নয় (এবং অনেক বেশি দক্ষ হতে পারে)। মনে রাখবেন যে কোড যেটি Log.v() কল করে সেটি কম্পাইল করা হয় এবং রিলিজ বিল্ডে এক্সিকিউট করা হয়, যার মধ্যে স্ট্রিং তৈরি করা হয়, এমনকি লগগুলি পড়া না হলেও।
  • যেকোন লগিং যা অন্য লোকেদের পড়ার জন্য এবং রিলিজ বিল্ডে উপলভ্য হওয়ার জন্য বোঝানো হয় তা রহস্যজনক না হয়ে তুচ্ছ হওয়া উচিত এবং বোধগম্য হওয়া উচিত। এর মধ্যে DEBUG স্তর পর্যন্ত সমস্ত লগ আপ অন্তর্ভুক্ত রয়েছে৷
  • যখন সম্ভব, এক লাইনে লগিং করতে থাকুন। 80 বা 100 অক্ষর পর্যন্ত লাইনের দৈর্ঘ্য গ্রহণযোগ্য। সম্ভব হলে প্রায় 130 বা 160 অক্ষরের (ট্যাগের দৈর্ঘ্য সহ) দৈর্ঘ্য এড়িয়ে চলুন।
  • যদি লগিং সাফল্যের প্রতিবেদন করে, VERBOSE এর চেয়ে উচ্চ স্তরে এটি ব্যবহার করবেন না।
  • আপনি যদি অস্থায়ী লগিং ব্যবহার করে এমন একটি সমস্যা নির্ণয় করতে চান যা পুনরুত্পাদন করা কঠিন, তাহলে এটিকে DEBUG বা VERBOSE স্তরে রাখুন এবং কম্পাইলের সময় এটিকে নিষ্ক্রিয় করার অনুমতি দেয় এমন ব্লকগুলির সাথে এটিকে আবদ্ধ করুন৷
  • লগের মাধ্যমে নিরাপত্তা ফাঁস সম্পর্কে সতর্ক থাকুন। ব্যক্তিগত তথ্য লগিং এড়িয়ে চলুন. বিশেষ করে, সুরক্ষিত বিষয়বস্তু সম্পর্কে তথ্য লগ করা এড়িয়ে চলুন। ফ্রেমওয়ার্ক কোড লেখার সময় এটি বিশেষভাবে গুরুত্বপূর্ণ কারণ ব্যক্তিগত তথ্য বা সুরক্ষিত সামগ্রী কী হবে এবং কী হবে না তা আগে থেকে জানা সহজ নয়৷
  • নেটিভ কোডের জন্য System.out.println() (বা printf() ব্যবহার করবেন না। System.out এবং System.err /dev/null এ পুনঃনির্দেশিত হয়, তাই আপনার প্রিন্ট স্টেটমেন্টের কোন দৃশ্যমান প্রভাব নেই। যাইহোক, এই কলগুলির জন্য ঘটে যাওয়া সমস্ত স্ট্রিং বিল্ডিং এখনও কার্যকর করা হয়।
  • লগিং করার সুবর্ণ নিয়ম হল যে আপনার লগগুলি অপ্রয়োজনীয়ভাবে অন্য লগগুলিকে বাফারের বাইরে ঠেলে দিতে পারে না, ঠিক যেমন অন্যরা আপনার লগগুলিকে বাইরে ঠেলে দিতে পারে না।

Javatests শৈলী নিয়ম

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

testMethod_specificCase1 testMethod_specificCase2

void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}