خلاصه کتاب کد تمیز – فصل پنجم : فرمت‌بندی
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 5 دقیقه

 خلاصه کتاب کد تمیز – فصل پنجم : فرمت‌بندی

درود به همه‌ی رفقا امیدوارم خوشحال و خندون باشین. توی این فصل قراره بریم ببینیم فرمت یه کد تمیز باید به چه شکل باشه تا وقتی ملت میان کد مارو میخونن تحت تاثیر نظم و انسجام و توجه ما به جز‌ئیات قرار بگیرن و بگن نه بابا! چه ادم حرفه‌ای پشت این داستان بوده! نه اینکه بگن طرف سرمست و شاد بوده و نمیفهمیده چیکار میکنه.

هدف ما از فرمت بندی چیه؟

این کار خیلی خیلی مهمه و انجام دادنش واااجبه، برای برقراری ارتباط، باید کدتون فرمت بندی بشه و ارتباطات مهم ترین بخش برای برنامه‌نویسای حرفه‌ایه؛ حالا اگه از یه سری قوانین ساده تبعیت کنین خیلی شیک میتونین کدتون رو فرمت بندی کنین؛ البته لازم به ذکره اگه توی یک تیم هستین و اونجا یه سری قوانین تعریف کردن باید از همونا پیروی کنین تا یه دست باشین؛ در همین راستا داشتن یک ابزار خودکار برای اعمال این فرمت‌ها هم میتونه کمک کننده باشه.

فرمت‌بندی عمودی یا Vertical

نکته‌ی مهم در این بخش اینه که هر فایل نباید بیش‌تر از ۵۰۰ خط کد داشته باشه، این باید خیلی مورد توجه قرار بگیره چراکه درک فایل‌های کوچیک معمولا خیلی اسون‌تر از درک فایل‌های بزرگ هست.

The Newspaper Metaphor

خوندن کد از بالا به پایین مثل خوندن یه روزنامه میمونه، درواقع شما وقتی روزنامه میخونید انتظار دارید اول یه عنوان داشته باشه که بگه داستان از چه قراره، بعد مثلا پاراگراف اول یه خلاصه از کل داستانو بگه بدون جزئیات؛ و هر چی به سمت پایین میریم جزئیات کار بیش‌تر میشه و تا جایی پیش میریم که از ریز ماجرا باخبر میشیم.

یک فایل حاوی کد هم باید به همین صورت باشه، در ابتدا نام باید ساده اما توضیحی باشه و خودکار به ما بگه آيا الان توی فایل یا ماژول درستی هستیم یا نه. بالاترین قسمت فایل باید مفاهیم و الگوریتم‌های سطح بالایی رو نشون بده و همینطور که به سمت پایین میریم جزئیات کار زیاد بشه تا جایی که از جزئیات سطح پایین فایل هم باخبر بشیم.

فاصله عمودی بین مفاهیم

بین هر مفهومی که توی کد ما وجود داره باید فاصله بزاریم چون هر چند خط از کد ما نشون دهنده‌ی یک تفکر کامل هست. این مورد از نظر بصری اهمیت بالایی داره،‌میگید نه؟ خب خودتون قضاوت کنین‌ با کدوم راحت ترین؟

Listing 5-1

BoldWidget.java

package fitnesse.wikitext.widgets;

import java.util.regex.*;

public class BoldWidget extends ParentWidget {
	public static final String REGEXP = "'''.+?'''";
	private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
		Pattern.MULTILINE + Pattern.DOTALL
	);

	public BoldWidget(ParentWidget parent, String text) throws Exception {
		super(parent);
		Matcher match = pattern.matcher(text);
		match.find();
		addChildWidgets(match.group(1));
	}

	public String render() throws Exception {
		StringBuffer html = new StringBuffer("<b>");
		html.append(childHtml()).append("</b>");
		return html.toString();
	}
}

یا این یکی ؟

Listing 5-2

BoldWidget.java

package fitnesse.wikitext.widgets;
import java.util.regex.*;
public class BoldWidget extends ParentWidget {
        public static final String REGEXP = "'''.+?'''";
        private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
        Pattern.MULTILINE + Pattern.DOTALL);
        public BoldWidget(ParentWidget parent, String text) throws Exception {
                super(parent);
                Matcher match = pattern.matcher(text);
                match.find();
                addChildWidgets(match.group(1));
        }
        public String render() throws Exception {
                StringBuffer html = new StringBuffer("<b>");
                html.append(childHtml()).append("</b>");
                return html.toString();
        }
}

 تراکم عمودی

به این نمونه‌ای که در ادامه براتون میزارم دقت کنین، اگه قراره فاصله بین هر چند خط، مفاهیم مختلف رو از هم جدا کنه، پس تراکم بین چیزایی که به هم مرتبط هستن هم مهمه. مثلا اگه یه متغییر مربوط به فانکشنه نرین ۵ خط بالاتر تعریفش کنین همون نزدیک این کارو انجام بدین( البته این شامل تعریف متغییرهای سراسری که اول کار تعریف میکنین نمیشه).

بریم سراغ مثال :

به این کد دقت کنین.

Listing 5-3

/**
	* The class name of the reporter listener
	*/
	private String m_className;
	
	/**
	* The properties of the reporter listener
	*/
	private List<Property> m_properties = new ArrayList<Property>();
	
	public void addProperty(Property property) {
		m_properties.add(property);
	}
}

حالا به این یکی نگاه کنین که چقدر راحت تره و همه‌ چی رو توی یک نگاه متوجه میشین.

Listing 5-4

public class ReporterConfig {
	private String m_className;
	private List<Property> m_properties = new ArrayList<Property>();
	public void addProperty(Property property) {
		m_properties.add(property);
	}
}

فاصله عمودی

اقاجون مفاهیمی که باهم ارتباط تنگاتنگ دارن رو باید نزدیک به هم نگه دارین تا نخوایین کل فایل رو مدام بالا پایین کنین. البته که این قانون برای مفاهیمی که توی فایل‌های جداگونه هستن صدق نمیکنه ولی مفاهیم مرتبطی که توی یک فایل هستن باید نزدیک هم باشن مگه اینکه دلیل خیلی خوبی برای جداییشون داشته باشین.

یه مثال خوشگل و کوچیک :

public int countTestCases() {
        int count= 0;
        for (Test each : tests)
        count += each.countTestCases();
        return count;
}

ترتیب عمودی

باید تابعی که فراخوانی میشه زیر تابعی باشه که فراخوانی رو انجام می‌ده این یه جریان قشنگِ سطح بالا به سطح پایین رو شکل میده.

فرمت‌بندی افقی

فاصله افقی هم باید منطقی باشه و ترازبندی درستی داشته باشه. ( که الان IDE ها این کارو برامون انجام میدن)

Indentation یا تورفتگی

اگه این مورد رو رعایت نمیکنین خواهشا برنامه‌نویسی رو ببوسین بزارین کنار شما به درد این کارا نمیخورین؛ یه Indentation دیگه برادر من رعایت کن تا نفرینت نکنن.

قوانین تیم

درسته که هر کسی استایل کدنویسی خودش رو داره ولی وقتی توی یک تیم قرار میگیرین باید طبق قانون‌های تیم عمل کنین تا همه یک دست پیش برین.

قوانین فرمت‌بندی عموباب

در آخرم این کد رو به عنوان نمونه ببینین که یه مثال استاندارد هست و قوانینیه که خود عموباب ازشون استفاده میکنه:

Listing 5-6

CodeAnalyzer.java

public class CodeAnalyzer implements JavaFileAnalysis {
	private int lineCount;
	private int maxLineWidth;
	private int widestLineNumber;
	private LineWidthHistogram lineWidthHistogram;
	private int totalChars;
	public CodeAnalyzer() {
		lineWidthHistogram = new LineWidthHistogram();
	}
	public static List<File> findJavaFiles(File parentDirectory) {
		List<File> files = new ArrayList<File>();
		findJavaFiles(parentDirectory, files);
		return files;
	}
	private static void findJavaFiles(File parentDirectory, List<File> files) {
		for (File file : parentDirectory.listFiles()) {
			if (file.getName().endsWith(".java"))
			files.add(file);
			else if (file.isDirectory())
			findJavaFiles(file, files);
		}
	}
	public void analyzeFile(File javaFile) throws Exception {
		BufferedReader br = new BufferedReader(new FileReader(javaFile));
		String line;
		while ((line = br.readLine()) != null)
		measureLine(line);
	}
	private void measureLine(String line) {
		lineCount++;
		int lineSize = line.length();
		totalChars += lineSize;
		lineWidthHistogram.addLine(lineSize, lineCount);
		recordWidestLine(lineSize);
	}
	private void recordWidestLine(int lineSize) {
		if (lineSize > maxLineWidth) {
			maxLineWidth = lineSize;
			widestLineNumber = lineCount;
		}
	}
	public int getLineCount() {
		return lineCount;
	}
	public int getMaxLineWidth() {
		return maxLineWidth;
	}
	public int getWidestLineNumber() {
		return widestLineNumber;
	}
	public LineWidthHistogram getLineWidthHistogram() {
		return lineWidthHistogram;
	}
	public double getMeanLineWidth() {
		return (double)totalChars/lineCount;
	}
	public int getMedianLineWidth() {
		Integer[] sortedWidths = getSortedWidths();
		int cumulativeLineCount = 0;
		for (int width : sortedWidths) {
			cumulativeLineCount += lineCountForWidth(width);
			if (cumulativeLineCount > lineCount/2)
			return width;
		}
	throw new Error("Cannot get here");
	}
	private int lineCountForWidth(int width) {
		return lineWidthHistogram.getLinesforWidth(width).size();
	}
	private Integer[] getSortedWidths() {
		Set<Integer> widths = lineWidthHistogram.getWidths();
		Integer[] sortedWidths = (widths.toArray(new Integer[0]));
		Arrays.sort(sortedWidths);
		return sortedWidths;
	}
}

خب این فصل خیلی کوتاه بود و تموم شد،‌امیدوارم این موارد رو رعایت کنین و خوندن این مقاله هم براتون مفید بوده باشه. اگه هر نظر یا انتقادی دارین در بخش نظرات با ما درمیون بزارین و در نهایت از وقتی که برای مطالعه گذاشتید ممنونم.

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
4.67 از 6 رای

10 ماه پیش
کد_تمیز
clean_code
/@Fatemeh.shirzadfar
فاطمه شیرزادفر
برنامه نویس

تجربه کلمه‌ای هست که همه برای توصیف اشتباهاتشون ازش استفاده میکنن، و من همیشه دنبال اشتباهات جدیدم! برنامه‌نویس هستم و لینوکس‌ دوست

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

فاطمه شیرزادفر

برنامه نویس