پاسخ به بازخوردهای پروژهها
در این بازسازی، با قطعه کدی روبرو هستیم که میتوانیم آن را به صورت یک متد جدید، گروهبندی کنیم. نام متد، توضیح دهنده عملیاتی است که توسط آن قطعه کد انجام میشود.
این بازسازی یکی از پر استفادهترین بازسازیهای کد است. معمولا زمانیکه متدی بلند باشد یا تکه کدی نیاز به کامنتی برای توضیح درباره کاری که انجام میدهد داشته باشد، چنین بازسازی ای نیاز است. در صورتیکه نام متدها به طور مناسبی انتخاب شوند، ایجاد متدهای کوچک از دو جهت مفید است:
- خواندن متن متدهای بالادستی را آسانتر میکند. در واقع نام متد عملا نقش کامنت را ایفا میکند. مراجعه کنید به Self documenting code
- احتمال اینکه متدها دوباره استفاده شوند را بالا میبرد
الگوهای متفاوتی در مورد طول متدها وجود دارد. ولی قاعده کلی حاکم بر این مورد «ارتباط منطقی بدنه و نام متد» است. در صورت رعایت این قاعده، عموما متدهایی با اندازه مناسب بهوجود میآیند.
بهطور مثال قطعه کد زیر را مشاهده کنید:
public void PrintInfo(dynamic person) { Console.WriteLine(person.Name); Console.WriteLine(person.LastName); Console.WriteLine(person.Job.Title); Console.WriteLine(person.Job.Salary); }
این قطعه کد را میتوان به صورت زیر بازسازی کرد:
public void PrintInfo(dynamic person) { Console.WriteLine(person.Name); Console.WriteLine(person.LastName); PrintJob(person.Job); } public void PrintJob(dynamic job) { Console.WriteLine(job.Title); Console.WriteLine(job.Salary); }
مراحل انجام این بازسازی کد
بعد از تشخیص تکه کدی که نیاز به استخراج متد در آن وجود دارد، مراحل زیر را انجام دهید:
- متد جدیدی ایجاد کنید و نام آن را بر اساس کاری که قرار است تکه کد انتخاب شده انجام دهد، تعیین کنید (نام را بر اساس کاری که قرار است انجام دهد انتخاب نمایید؛ نه نحوه انجام دادن آن کار).
- تکه کد نیازمند استخراج را از بدنه متد قبلی به بدنه متد جدید کپی کنید.
- کد استخراج شده را برای پیدا کردن متغیرهای محلی بهجا مانده از متد اصلی بررسی کنید. این متغیرها احتمالا متغیرهای محلی متد جدید و پارامترهای آن را تشکیل خواهند داد.
- اگر متغیرهای محلی موجود در تکه کد استخراج شده فقط در آن استفاده شدهاند، آنها را به صورت متغیرهای محلی موقتی در متد جدید ایجاد کنید.
- متغیرهای محلی تکه کد استخراج شده را بررسی کنید که آیا در جایی از آن ویرایش شدهاند یا خیر؟ در صورتیکه ویرایش شده باشند، بررسی کنید که آیا میتوان آن را به عنوان خروجی متد جدید در نظر گرفت و متغیرها را مقداردهی کرد یا خیر؟ (توضیح بیشتر در مثال)
- پارامترهای متناظری را با متغیرهای محلی موقتی ایجاد شده، در متد جدید ایجاد کنید.
- بعد از این که تکلیف تمامی متغیرهای محلی مشخص شد، کد را کامپایل کنید.
- در متد مبدا تکه کد استخراج شده را به فراخوانی متد جدید تغییر دهید.
- کد را کامپایل و تست کنید .
مثال: تکه کدی با ویرایش کردن متغیرهای محلی
سادهترین حالتیکه کد استخراج شده از متغیرهای محلی متد مبدا استفاده میکند زمانی است که تنها مقادیر این متغیرها را میخواند. مثال ذکر شده در ابتدای نوشتار از این نوع است.
زمانی که متغیری در تکه کد استخراج شده ویرایش شده باشد، معمولا با دو حالت روبرو هستیم:
- متغیر ویرایش شده فقط در تکه کد استخراج شده ویرایش و استفاده شدهاست.
- متغیر ویرایش شده بعد از تکه کد استخراج شده نیز در بدنه متد اصلی مورد استفاده قرار گرفتهاست.
در حالت دوم نیاز است مقدار متغیر ویرایش شده، به متد بالادستی برگردانده شود. به طور مثال تکه کدی را در نظر بگیرید که مقدار رقم نهایی قابل پرداخت یک آیتم سفارش را در آن مقداردهی میکند. این روال را میتوان به صورت زیر پیاده سازی کرد:
public void SetPayableAmount(dynamic orderItem) { var price = orderItem.Price; var discount = 0; var discountPlan = GetDiscountPlan(); var discountPercentage = discountPlan.Percentage; discount = price * discountPercentage; orderItem.PayableAmount = orderItem.Price - discount } private dynamic GetDiscountPlan() { throw new NotImplementedException(); }
با کمی دقت در تکه کد بالا میتوان به این نتیجه رسید که جدا کردن روال محاسبه تخفیف یک طراحی و بازسازی خوب است. در سه خطی که مربوط به محاسبه تخفیف است یک متغیر محلی به نام discount مقداردهی شده است و یک متغیر محلی به نام price فقط خوانده شدهاست. این کد را میتوان به صورت زیر بازسازی کرد:
public void SetPayableAmount(dynamic orderItem) { var price = orderItem.Price; var discount = GetDiscount(price); orderItem.PayableAmount = orderItem.Price - discount; } public dynamic GetDiscount(decimal price) { var discountPlan = GetDiscountPlan(); var discountPercentage = discountPlan.Percentage; return price * discountPercentage; } private dynamic GetDiscountPlan() { throw new NotImplementedException(); }
در این بازسازی، به دلیل نیاز کد استخراج شده به مقدار متغیر price، این متغیر را به صورت یک پارامتر، به متد جدید ایجاد شده، ارسال کردیم. همچین مقدار تخفیف محاسبه شده را نیز به دلیل نیاز به آن در متد بالادستی به صورت مقدار خروجی به آن متد بازگرداندیم.
ابزارهای کمکی برای این بازسازی کد
در ابزارهای زیر امکاناتی برای انجام این بازسازی کد تعبیه شده است:
مایکروسافت ویژوال استودیو: میانبر Ctrl+R,M را بعد از انتخاب کد منتخب برای استخراج، استفاده نمایید.
Jetbrains Resharper: این ابزار را میتوان با میانبرهای مایکروسافت ویژوال استودیو استفاده کرد. امکانات کلی این ابزار از امکانات موجود در مایکروسافت ویژوال استودیو بیشتر است.
مطالب دورهها
لیست ها و آرایه ها در #F
برای تعریف لیست در #F فقط کافیست از [] و برای جداسازی آیتمهای موجود در لیست از عملگر :: (بخوانید cons) استفاده کنید. #F از لیستهای خالی نیز پشتیبانی میکند. به مثال هایی از این دست توجه کنید
#1 تعریف یک لیست خالی
#2 تعریف یک لیست به همراه یک آیتم
#3 تعریف یک لیست به همراه دو آیتم
قبول دارم که دستورالعمل بالا برای مقدار دهی اولیه به لیست کمی طولانی و سخت است. برای همین میتونید از روش زیر هم استفاده کنید.
*کد بالا یک لیست با دو آیتم که از نوع رشته ای هستند تولید خواهد کرد.
میتونید از عملگر @ برای پیوستن دو لیست به هم نیز استفاده کنید.
نکته : تمام آیتمهای موجود در لیست باید از یک نوع باشند. بعنی امکان تعریف لیستی که دارای آیتم هایی با datatypeهای متفاوت باشد باعث تولید خطای کامپایلری میشود. اما اگر نیاز به لیستی دارید که باید چند datatype رو هم پوشش دهد میتونید از objectها استفاده کنید.
در بالا یک لیست از objectها رو تعریف کرده ایم. فقط دقت کنید برای اینکه آیتمهای موجود در لیست رو تبدیل به object کنیم از دستور box قبل از هر آیتم استفاده کردیم.
در هنگام استفاده از عملگرها @ و :: مقدار لیست تغییر نمیکند بلکه یک لیست جدید تولید خواهد شد.
#1 تعریف لیستی که دارای یک آیتم است.
#2 تعریف لیستی که دارای دو آیتم است(آیتم دوم لیست خود از نوع لیست است)
#3 تعریف لیستی که دارای سه آیتم است(ایتم دوم لیست خود از نوع لیستی است که دارای دو آیتم است)
# از تابع List.rev برای معکوس کردن آیتمهای لیست three استفاده کردیم و مقادیر در لیستی به نام rightWayRound قرار گرفت.
#5 تابع main برای چاپ اطلاعات لیست ها
بعد از اجرا خروجی زیر مشاهده میشود.
تفاوت بین لیستها در #F و لیست و آرایه در دات نت(System.Collection.Generic)
#1 در #F بعد از ساختن یک لیست امکان تغییر در مقادیر عناصر آن وجود ندارد.
#2 در #F بعد از ساختن یک لیست دیگه نمیتونید یک عنصر جدید به لیست اضافه کنید.
#3 جستجوی در لیستهای #F به نسبت لیستها و آرایههای در دات نت کندتر عمل میکند.
استفاده از عبارات در لیست ها
برای تعریف محدوده در لیست میتونیم به راحتی از روش زیر استفاده کنیم
برای ساخت لیستها به صورت داینامیک استفاده از حلقههای تکرار در لیست مجاز است.
کد بالا معادل کد زیر در #C است.
لیستها و الگوی Matching
روش عادی برای کار با لیستها در #F استفاده از الگوی Matching و توابع بازگشتی است.
در مثال بالا ابتدا یک لیست تعریف کردیم که دارای 3 آیتم است و هر آیتم آن خود یک لیست با سه آیتم است.(تمام آیتمها از نوع داده عددی هستند). یک تابع بازگشتی برای پیمایش تمام آیتمهای لیست نوشتم که در اون از الگوی Matching استفاده کردیم.
خروجی :
ماژول لیست
در جدول زیر تعدادی از توابع ماژول لیست رو مشاهده میکنید.
مثال هایی از توابع بالا
مثال هایی از نحوه استفاده seq
#1 seq بامحدوده 1 تا 100 و توالی 10
#2 استفاده از حلقههای تکرار برای تعریف محدوده و توالی در seq
#3 استفاده از <- به جای yield
#4 استفاده از حلقه for به همراه شرط برای فیلتر کردن
چگونگی استفاده از توابع seq
در این بخش به ارائه مثال هایی کاربردیتر از چگونگی استفاده از seq در #F میپردازیم. برای شروع نحوه ساخت یک seq خالی یا empty رو خواهم گفت.
روش ساخت یک seq که فقط یک عنصر را برگشت میدهد.
برای ساختن یک seq همانند لیستها میتونیم از seq.init استفاده کنیم. عدد 5
که بلافاصله بعد از تابع seq.init آمده است نشان دهنده تعداد آیتمها
موجود در seq خواهد بود. seq.iter هم یک تابع مورد نظر رو بر روی تک تک
عناصر seq اجرا خواهد کرد.(همانند list.iter)
خروجی مثال بالا
با استفاده از توابع seq.ofArray , seq.ofList میتونیم seq مورد نظر خود را از لیست یا آرایه مورد نظر بسازیم.
البته این نکته رو هم یادآور بشم که به کمک عملیات تبدیل نوع(type casting) هم میتونیم آرایه رو به seq تبدیل کنیم. به صورت زیر
برای مشخص کردن اینکه آیا یک آیتم در seq موجود است یا نه میتونیم از seq.exists به صورت زیر استفاده کنیم.
اگر seq پاس داده شده به تابع exists خالی باشد یا یک ArgumentNullException متوقف خواهید شد.
برای جستجو و پیدا کردن یک آیتم در seq میتونیم از seq.find استفاده کنیم.
دقت کنید که اگر هیچ آیتمی در sequence با predicate مورد نظر پیدا نشود
یک KeyNotFoundException رخ خواهد داد. در صورتی که مایل نباشید که استثنا
رخ دهد میتوانید از تابع seq.tryFind استفاده کنید. هم چنین خالی بودن
sequence ورودی باعث ArgumentNullExceptionخواهد شد.
استفاده از lambda expression در توابع
lamdaExpressoion از تواناییها مورد علاقه برنامه نویسان دات نت است و کمتر کسی است حاضر به استفاده از آن در کوئریهای linq نباشد. در #F نیز میتوانید از lambda Expression استفاده کنید. در ادامه به بررسی مثال هایی از این دست خواهیم پرداخت.
تابع skipWhile
همانند skipWhile در linq عمل میکند. یعنی یک predicate مورد نظر را بر روی تک تک عناصر یک لیست اجرا میکند و آیتم هایی که شرط برای آنها true باشد نادیده گرفته میشوند و مابقی آیتمها برگشت داده میشوند.
میبینید که predicate
مورد نظر برای تابع skipWhile به صورت lambda expression است که با رنگ
متفاوت نمایش داده شده است.(استفاده از کلمه fun).
خروجی به صورت زیر است:
برای
بازگرداندن یک تعداد مشخص از آیتمهای seq میتونید از توابع seq.take یا
seq.truncate استفاده کنید. ابتدا باید تعداد مورد نظر و بعد لیست مورد نظر
را به عنوان پارامتر مقدار دهی کنید.
مثال:
خروجی
Tuples
tuples در #F به گروهی از مقادیر بی نام ولی مرتب شده که میتوانند انواع متفاوت هم داشته باشند گفته میشود. ساختار کلی آن به صورت ( element , ... , element ) است که هر element خود میتواند یک عبارت نیز باشد.(مشابه کلاس Tuple در #C که به صورت generic استفاده میکنیم)
نکات استفاده از tuple
#1 میتونیم از الگوی Matching برای دسترسی به عناصر tuple استفاده کنیم.
#2 میتونیم از let برای تعربف الگوی tuple استفاده کنیم.
#3 توابع fst و snd مقادیر اول و دوم هر tuple رو بازگشت میدهند
#4 تابعی برای بازگشت عنصر سوم یک tuple وجود ندارد ولی این تابع رو با هم مینویسیم:
کاربرد tuple در کجاست
زمانی که یک تابع باید بیش از یک مقدار را بازگشت دهد از tupleها استفاده میکنیم. برای مثال
خروجی تابع divRem از نوع tuple که دارای 2 مقدار است میباشد.
#1 let emptyList = [] #2 let oneItem = "one " :: [] #3 let twoItem = "one " :: "two " :: []
#2 تعریف یک لیست به همراه یک آیتم
#3 تعریف یک لیست به همراه دو آیتم
قبول دارم که دستورالعمل بالا برای مقدار دهی اولیه به لیست کمی طولانی و سخت است. برای همین میتونید از روش زیر هم استفاده کنید.
let shortHand = ["apples "; "pears"]
میتونید از عملگر @ برای پیوستن دو لیست به هم نیز استفاده کنید.
let twoLists = ["one, "; "two, "] @ ["buckle "; "my "; "shoe "]
نکته : تمام آیتمهای موجود در لیست باید از یک نوع باشند. بعنی امکان تعریف لیستی که دارای آیتم هایی با datatypeهای متفاوت باشد باعث تولید خطای کامپایلری میشود. اما اگر نیاز به لیستی دارید که باید چند datatype رو هم پوشش دهد میتونید از objectها استفاده کنید.
let objList = [box 1; box 2.0; box "three"]
در هنگام استفاده از عملگرها @ و :: مقدار لیست تغییر نمیکند بلکه یک لیست جدید تولید خواهد شد.
#1 let one = ["one "] #2 let two = "two " :: one #3 let three = "three " :: two #4 let rightWayRound = List.rev three #5 let main() = printfn "%A" one printfn "%A" two printfn "%A" three printfn "%A" rightWayRound
#2 تعریف لیستی که دارای دو آیتم است(آیتم دوم لیست خود از نوع لیست است)
#3 تعریف لیستی که دارای سه آیتم است(ایتم دوم لیست خود از نوع لیستی است که دارای دو آیتم است)
# از تابع List.rev برای معکوس کردن آیتمهای لیست three استفاده کردیم و مقادیر در لیستی به نام rightWayRound قرار گرفت.
#5 تابع main برای چاپ اطلاعات لیست ها
بعد از اجرا خروجی زیر مشاهده میشود.
["one "] ["two "; "one "] ["three "; "two "; "one "] ["one "; "two "; "three "]
F#List | Net Array | Net List | |
#1 امکان تغییر در عناصر لیست | No | Yes | Yes |
#2 امکان اضافه کردن عنصر جدید | No | No | Yes |
#3 جستجو | On | O1 | O1 |
#2 در #F بعد از ساختن یک لیست دیگه نمیتونید یک عنصر جدید به لیست اضافه کنید.
#3 جستجوی در لیستهای #F به نسبت لیستها و آرایههای در دات نت کندتر عمل میکند.
استفاده از عبارات در لیست ها
برای تعریف محدوده در لیست میتونیم به راحتی از روش زیر استفاده کنیم
let rangeList = [1..99]
let dynamicList = [for x in 1..99 -> x*x]
for(int x=0;x<99 ; x++) { myList.Add(x*x); }
روش عادی برای کار با لیستها در #F استفاده از الگوی Matching و توابع بازگشتی است.
let listOfList = [[2; 3; 5]; [7; 11; 13]; [17; 19; 23; 29]] let rec concatList l = match l with | head :: tail -> head @ (concatList tail) | [] -> [] let primes = concatList listOfList printfn "%A" primes
خروجی :
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29]
در جدول زیر تعدادی از توابع ماژول لیست رو مشاهده میکنید.
نام تابع | توضیحات |
List.length | تابعی که طول لیست را برمی گرداند |
List.head | تابعی برای برگشت عنصر اول لیست |
List.tail | تمام عناصر لیست را بر میگرداند به جز عنصر اول |
List.init | یک لیست با توجه به تعداد آیتم ایجاد میکند و یم تابع را بر روی تک تک عناصر لیست ایجاد میکند. |
List.append | یک لیست را به عنوان ورودی دریافت میکند و به لیست مورد نظر اضافه میکند و مجموع دو لیست را برگشت میدهد |
List.filter | فقط عناصری را برگشت میدهد که شرط مورد نظر بر روی آنها مقدار true را برگشت دهد |
List.map | یک تابع مورد نظر را بر روی تک تک عناصر لیست اجرا میکند و لیست جدید را برگشت میدهد |
List.iter | یک تابع مورد نظر را بر روی تک تک عناصر لیست اجرا میکند |
List.zip | مقادیر دو لیست را با هم تجمیع میکند و لیست جدید را برگشت میدهد. اگر طول 2 لیست ورودی یکی نباشد خطا رخ خواهدداد |
List.unzip | درست برعکس تابع بالا عمل میکند |
List.toArray | لیست را تبدیل به آرایه میکند |
List.ofArray | آرایه را تبدیل به لیست میکند |
List.head [5; 4; 3] List.tail [5; 4; 3] List.map (fun x -> x*x) [1; 2; 3] List.filter (fun x -> x % 3 = 0) [2; 3; 5; 7; 9]
Sequence Collection
seq در #F یک توالی از عناصری است که هم نوع باشند. عموما از sequenceها زمانی استفاده میکنیم که یک مجموعه از دادهها با تعداد زیاد و مرتب شده داشته باشیم ولی نیاز به استفاده از تمام عناصر آن نیست. کارایی sequence در مجموعههای با تعداد زیاد از listها به مراتب بهتر است. sequenceها را با تابع seq میشناسند که معادل IEnumerable در دات نت است. بنابر این هر مجمو عه ای که IEnumerable رو در دات نت پیاده سازی کرده باشد در #F با seq قابل استفاده است.مثال هایی از نحوه استفاده seq
#1 seq بامحدوده 1 تا 100 و توالی 10
seq { 0 .. 10 .. 100 }
seq { for i in 1 .. 10 do yield i * i }
seq { for i in 1 .. 10 -> i * i }
let isprime n = let rec check i = i > n/2 || (n % i <> 0 && check (i + 1)) check 2 let aSequence = seq { for n in 1..100 do if isprime n then yield n }
در این بخش به ارائه مثال هایی کاربردیتر از چگونگی استفاده از seq در #F میپردازیم. برای شروع نحوه ساخت یک seq خالی یا empty رو خواهم گفت.
let seqEmpty = Seq.empty
let seqOne = Seq.singleton 10
let seqFirst5MultiplesOf10 = Seq.init 5 (fun n -> n * 10) Seq.iter (fun elem -> printf "%d " elem) seqFirst5MultiplesOf10
0 10 20 30 40
let seqFromArray2 = [| 1 .. 10 |] |> Seq.ofArray
let seqFromArray1 = [| 1 .. 10 |] :> seq<int>
let containsNumber number seq1 = Seq.exists (fun elem -> elem = number) seq1 let seq0to3 = seq {0 .. 3} printfn "For sequence %A, contains zero is %b" seq0to3 (containsNumber 0 seq0to3)
برای جستجو و پیدا کردن یک آیتم در seq میتونیم از seq.find استفاده کنیم.
let isDivisibleBy number elem = elem % number = 0 let result = Seq.find (isDivisibleBy 5) [ 1 .. 100 ] printfn "%d " result
استفاده از lambda expression در توابع
lamdaExpressoion از تواناییها مورد علاقه برنامه نویسان دات نت است و کمتر کسی است حاضر به استفاده از آن در کوئریهای linq نباشد. در #F نیز میتوانید از lambda Expression استفاده کنید. در ادامه به بررسی مثال هایی از این دست خواهیم پرداخت.
تابع skipWhile
همانند skipWhile در linq عمل میکند. یعنی یک predicate مورد نظر را بر روی تک تک عناصر یک لیست اجرا میکند و آیتم هایی که شرط برای آنها true باشد نادیده گرفته میشوند و مابقی آیتمها برگشت داده میشوند.
let mySeq = seq { for i in 1 .. 10 -> i*i }
let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""
let mySeqSkipWhileLessThan10 = Seq.skipWhile (fun elem -> elem < 10) mySeq
mySeqSkipWhileLessThan10 |> printSeq
خروجی به صورت زیر است:
16 25 36 49 64 81 100
مثال:
let mySeq = seq { for i in 1 .. 10 -> i*i } let truncatedSeq = Seq.truncate 5 mySeq let takenSeq = Seq.take 5 mySeq let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""
#1 truncatedSeq |> printSeq #3 takenSeq |> printSeq
1 4 9 16 25 //truncate 1 4 9 16 25 //take
Tuples
tuples در #F به گروهی از مقادیر بی نام ولی مرتب شده که میتوانند انواع متفاوت هم داشته باشند گفته میشود. ساختار کلی آن به صورت ( element , ... , element ) است که هر element خود میتواند یک عبارت نیز باشد.(مشابه کلاس Tuple در #C که به صورت generic استفاده میکنیم)
// Tuple of two integers. ( 1, 2 ) // Triple of strings. ( "one", "two", "three" ) // Tuple of unknown types. ( a, b ) // Tuple that has mixed types. ( "one", 1, 2.0 ) // Tuple of integer expressions. ( a + 1, b + 1)
#1 میتونیم از الگوی Matching برای دسترسی به عناصر tuple استفاده کنیم.
let print tuple1 = match tuple1 with | (a, b) -> printfn "Pair %A %A" a b
let (a, b) = (1, 2)
let c = fst (1, 2) // return 1 let d = snd (1, 2)// return 2
let third (_, _, c) = c
زمانی که یک تابع باید بیش از یک مقدار را بازگشت دهد از tupleها استفاده میکنیم. برای مثال
let divRem a b = let x = a / b let y = a % b (x, y)
بسیاری از عزیزانی که با Elmah کار کردهاند ، احتمالا زمانیکه تعداد رکوردها زیاد میشود و بخواهند مورد خاصی را جستجو یا پیگیری کنند مجبورند خروجی اکسل رو فیلتر کنن که این کار زمان بر است. اگر تعداد رکوردها زیاد باشد، باید از طریق خود جدول داخل دیتابیس رکورد مورد نظر خود را جستجو کنن. در این مطلب قصد دارم ابزاری که open source هست رو معرفی کنم که به کمک این ابزار به راحتی میتوانید خطای خاصی را جستجو کنید و حتی آماری از تعداد رکوردها در بازههای زمانی مختلف داشته باشید. همچنین میتوانید با دخل و تصرف در کد این برنامه آن را به صورت دلخواه تغییر دهید.
چند روزی هست که به دلیل قطعی کابل، فایلهای فلش سایتها از کار افتاده!
فایلهای فلش را بر اساس mime type آنها فیلتر کردهاند یعنی هر چه application/x-shockwave-flash که از طرف وب سرور شما سرو شود فیلتر میشود.
یک راه حل این است که پسوند تمام فایلهای فلش را تغییر داد تا وب سرور دیگر این mime type را از خودش بروز ندهد (در یک وب سرور هر mime type دقیقا به یک یا چند نوع پسوند فایل map شده). این مورد نیاز به اصلاح تمام صفحات سایت نیز خواهد داشت (علاوه بر تغییر پسوند فایلهای موجود). خوشبختانه فلش پلیر کاری به mime type یا حتی پسوند فایل، جهت نمایش آن ندارد.
راه حل سادهتر (بدون نیاز به تغییری در فایلها) هم این است که کمی تغییرات وب سرور خود را تغییر داد:
در IIS6 :
در IIS7 :
کلا mime type موجود را به برای مثال image/png تغییر دهید تا قسمتهای از کار افتاده سایت مجددا برقرار شود و آبروی کاری رفته مجددا به جوی بازگردد.
نظرات اشتراکها
معرفی Oracle Forms
این محیط آسانترین و راحترین محیط توسعه برای برنامه نویس هایی هست که میخواهند با پایگاه داده اوراکل کار کنند. و دوره آموزش و یادگیری سریعی داره و سرعت تولید سیستم آن از هر محیطی که تا به حال دیدم سریعتر هست.
اشتراکها
قوانین طراحی ساده
یک از ارزشهای XP، سادگی و یکی از تکنیکهای آن طراحی ساده (Simple Design) هست. Kent Beck مبدع XP برای داشتن یک طراحی ساده چهار قانون تعریف کردن که عبارتاند از:
- پاس شدن همه تستها
- عدم وجود تکرار
- بیان مقصود برنامه نویس
- کاهش تعداد کلاسها و متدها
در داکیومنتها به این نکته اشاره شده که سرویسهای scoped، نیازی به طراحی به صورت thread-safe نیستند و امن هستند.
آیا این به معنی این هست که ذاتا در درون هر وب ریکوئست و در یک ترد، امن هستند ولی به منزله thread-safe بودنشون در برنامه نویس multithread نیست؟