استفاده از چند فرم در کنار هم در ASP.NET MVC
searcher.Search(query, 10)
- در مورد اعراب زبان عربی به صورت پیش فرض خیر. اما اگر به کدهای فوق دقت کرده باشید از یک StandardAnalyzer توکار استفاده شده. این مورد یک سری تنظیمات ابتدایی را به همراه دارد. اگر کارکرد آن مورد قبول شما نیست میتونید خودتون یک Analyzer سفارشی رو توسعه بدید.
برای مثال یک نمونه سورس باز رو اینجا میتونید پیدا کنید که مباحث اعراب گذاری، ی و ک فارسی و عربی، یک سری stopword فارسی و مسایل دیگر را هم لحاظ کرده.
FirstName
firstName
strFirstName lblFirstName
<Company>.<Technology|Produt|Project>[.<Feature>][.<SubNamespace>]
Microsoft.Reporting.WebForms Kara.Support.Manager.Enums Kara.CSS.HQ.WebUI.Configuration
PackageManager , PacakgeConfigGenerator Circle , Utility , Package
CreateConfig , classdata CManager , ClsPackage , Config_Creator , Config1389
CenterCollection , PackageCollection
public delegate void Logger (string log); public delegate void LoggingCallback (object sender, string reason);
AddEventArgs , EditEventArgs , DeleteEventArgs
Adding , Add , Added
public delegate void <EventName>EventHandler (object sender, <EventName>EventArgs e);
public event EventHandler <AddEventArgs> Adding;
DisplayNameAttribute , MessageTypeAttribute
IComponent (اسم) IConnectionProvider (موصوف) ICloneable (صفت)
public enum FileMode { Append, Read, … }
[Flag] public enum KeyModifiers { Alt = 1, Control = 2, Shift = 4 }
public enum OperationState { DoneState, FaultState, RollbackState }
AddDays , Save , DeleteRow , BindData , Close , Open
Radius , ReportType , DataSource , Mode , CurrentCenterId
public CenterCollection Centers { get; set; }
if (list.Contains(item)) if (regularExpression.Matches(text)) if (stream.CanSeek) if (context.Created) if (form.Enabled)
if (list.IsContains(item)) if (regularExpression.Match(text)) if (stream.Seekable) if (context.IsCreated) if (form.IsEnabled)
public Color Color { get; set; }
firstName , e , id , packageId , centerName , name
public static MyType operator +(MyType left, MyType right) public static bool operator ==(MyType left, MyType right)
public static MyType operator ++(MyType value)
public static MyType operator /(MyType dividend, MyType divisor)
public static MyType operator -(MyType d1, MyType d2) // incorrect!
Area , DataBinder , PublicCacheName
_centersList _firstName _currentCenter
parameterType , packageOperationTypeId
lblName (Label) txtHeader (TextBox) btnSave (Button)
ArgumentNullException , InvalidOperaionException
System.Data
<Company>.<Component>.dll <Company>.<Project|Product|Technology>.<Component>.dll
Microsoft.CSharp.dll , Kara.CSS.Manager.dll
public int IComparer<T> {…} public delegate bool Predicate<T> (T item)
public int ISessionChannel<TSession> {…} public delegate TOutput Converter<TInput, TOutput> (TInput from) public class Nullable<T> {…} public class List<T> {…}
ArgumentExceptionIllegalCharacters ArgumentExceptionInvalidName ArgumentExceptionFileNotFound
Pascal Casing |
camel Casing |
Wrong |
Callback |
callback |
CallBack |
BitFlag |
bitFlag |
Bitflag / bitflag |
Canceled |
canceled |
Cancelled |
DoNot |
doNot |
Donot / Don’t |
|
|
|
Endpoint |
endpoint |
EndPoint / endPoint |
FileName |
fileName |
Filename / filename |
Gridline |
gridline |
GridLine / gridLine |
Hashtable |
hashtable |
HashTable / hashTable |
Id |
id |
ID |
Indexes |
indexes |
Indices |
LogOff |
logOff |
Logoff / LogOut ! |
LogOn |
logOn |
Logon / LogIn ! |
SignOut |
signOut |
Signout / SignOff |
SignIn |
signIn |
Signin / SignOn |
Metadata |
metadata |
MetaData / metaData |
Multipanel |
multipanel |
MultiPanel / multiPanel |
Multiview |
multiview |
MultiView / multiView |
Namespace |
namespace |
NameSpace / nameSpace |
Ok |
ok |
OK |
Pi |
pi |
PI |
Placeholder |
placeholder |
PlaceHolder / placeHolder |
UserName |
username |
Username / username |
WhiteSpace |
whiteSpace |
Whitespace / whitespace |
Writable |
writable |
Writeable / writeable |
public class Color { … public static Color FromArgb(…) { … } }
دلایل شانه خالی کردن از آزمایش واحد!
1- نوشتن آزمایشات زمان زیادی را به خود اختصاص خواهند داد.
مهمترین دلیلی که برنامهنویسها به سبب آن از نوشتن آزمایشات واحد امتناع میکنند، همین موضوع است. اکثر افراد به آزمایش بهعنوان مرحله آخر توسعه فکر میکنند. اگر این چنین است، بله! نوشتن آزمایشهای واحد واقعا سخت و زمانگیر خواهند بود. به همین جهت برای جلوگیری از این مساله روش pay-as-you-go مطرح شده است (ماخذ: کتاب Pragmatic Unit Testing در سی شارپ). یعنی با اضافه شدن هر واحد کوچکی به سیستم، آزمایش واحد آنرا نیز تهیه کنید. به این صورت در طول توسعه سیستم با باگهای کمتری نیز برخورد خواهید داشت چون اجزای آنرا در این حین به تفصیل مورد بررسی قرار دادهاید. اثر این روش را در شکل زیر میتوانید ملاحظه نمائید (تصویری از همان کتاب ذکر شده)
نوشتن آزمایشات واحد زمانبر هستند اما توسعه پیوسته آنها با به تاخیر انداختن آزمایشات به انتهای پروژه، همانند تصویر فوق تاثیر بسیار قابل توجهی در بهره وری شما خواهند داشت.
بنابراین اگر عنوان میکنید که وقت ندارید آزمایش واحد بنویسید، به چند سؤال زیر پاسخ دهید:
الف) چه مقدار زمان را صرف دیباگ کردن کدهای خود یا دیگران میکنید؟
ب) چه میزان زمان را صرف بازنویسی کدی کردهاید که تصور میرفت درست کار میکند اما اکنون بسیار مشکل زا ظاهر شده است؟
ج) چه مقدار زمان را صرف این کردهاید که منشاء باگ گزارش شده در برنامه را کشف کنید؟
برای افرادی که آزمایشات واحد را در حین پروسه توسعه در نظر نمیگیرند، این مقادیر بالا است و با ازدیاد تعداد خطوط سورس کدها، این ارقام سیر صعودی خواهند داشت.
تصویری از کتاب xUnit Test Patterns ، که بیانگر کاهش زمان و هزینه کد نویسی در طول زمان با رعایت اصول آزمایشات واحد است
2- اجرای آزمایشات واحد زمان زیادی را تلف میکند.
نباید اینطور باشد. عموما اجرای هزاران آزمایش واحد، باید در کسری از ثانیه صورت گیرد. (برای اطلاعات بیشتر به قسمت حد و مرز یک آزمایش واحد در قسمت قبل مراجعه نمائید)
3- امکان تهیه آزمایشات واحد برای کدهای قدیمی ( legacy code ) من وجود ندارد
برای بسیاری از برنامه نویسها، تهیه آزمایش واحد برای کدهای قدیمی بسیار مشکل است زیرا شکستن آنها به واحدهای کوچکتر قابل آزمایش بسیار خطرناک و پرهزینه است و ممکن است سبب از کار افتادن سیستم آنها گردد. اینجا مشکل از آزمایش واحد نیست. مشکل از ضعف برنامه نویسی آن سیستم است. روش refactoring ، طراحی مجدد و نوشتن آزمایشات واحد، به تدریج سبب طراحی بهتر برنامه از دیدگاههای شیءگرایی شده و نگهداری سیستم را در طولانی مدت سادهتر میسازد. آزمایشات واحد این نوع سیستمها را از حالت فلج بودن خارج میسازد.
4- کار من نیست که کدهای نوشته شده را آزمایش کنم!
باید درنظر داشته باشید که این هم کار شما نیست که انبوهی از کدهای مشکل دار را به واحد بررسی کننده آن تحویل دهید! همچنین اگر تیم آزمایشات و کنترل کیفیت به این نتیجه برسد که عموما از کدهای شما کمتر میتوان باگ گرفت، این امر سبب معروفیت و تضمین شغلی شما خواهد شد.
همچنین این کار شما است که تضمین کنید واحد تهیه شده مقصود مورد نظر را ارائه میدهد و اینکار را با ارائه یک یا چندین آزمایش واحد میتوان اثبات کرد.
5- تنها قسمتی از سیستم به من واگذار شده است و من دقیقا نمیدانم که رفتار کلی آن چیست. بنابراین آن را نمیتوانم آزمایش کنم!
اگر واقعا نمیدانید که این کد قرار است چه کاری را انجام دهید به طور قطع الان زمان مناسبی برای کد نویسی آن نیست!
6- کد من کامپایل میشود!
باید دقت داشت که کامپایلر فقط syntax کدهای شما را بررسی کرده و خطاهای آنرا گوشزد میکند و نه نحوهی عملکرد آنرا.
7- من برای نوشتن آزمایشات حقوق نمیگیرم!
باید اذعان داشت که به شما جهت صرف تمام وقت یک روز خود برای دیباگ کردن یک خطا هم حقوق نمیدهند! شما برای تهیه یک کد قابل قبول و قابل اجرا حقوق میگیرید و آزمایش واحد نیز ابزاری است جهت نیل به این مقصود (همانند یک IDE و یا یک کامپایلر).
8- احساس گناه خواهم کرد اگر تیم فنی کنترل کیفیت و آزمایشات را از کار بی کار کنم!!
نگران نباشید، این اتفاق نخواهد افتاد! بحث ما در اینجا آزمایش کوچکترین اجزا و واحدهای یک سیستم است. موارد دیگری مانند functional testing, acceptance testing, performance & environmental testing, validation & verification, formal analysis توسط تیمهای کنترل کیفیت و آزمایشات هنوز باید بررسی شوند.
9- شرکت من اجازه اجرای آزمایشات واحد را بر روی سیستمهای در حال اجرا نمیدهد.
قرار هم نیست بدهد! چون دیگر نام آن آزمایش واحد نخواهد بود. این آزمایشات باید بر روی سیستم شما و توسط ابزار و امکانات شما صورت گیرد.
پ.ن.
در هشتمین دلیل ذکر شده، از acceptance testing نامبرده شده. تفاوت آن با unit testing به صورت زیر است:
آزمایش واحد:
توسط برنامه نویسها تعریف میشود
سبب اطمینان خاطر برنامه نویسها خواهد شد
واحدهای کوچک سیستم را مورد بررسی قرار میدهد
یک آزمایش سطح پائین ( low level ) به شمار میرود
بسیار سریع اجرا میشود
به صورت خودکار (100 درصد خودکار است) و با برنامه نویسی قابل کنترل است
اما در مقابل آزمایش پذیرش به صورت زیر است:
توسط مصرف کنندگان تعریف میشود
سبب اطمینان خاطر مصرف کنندگان میشود.
کل برنامه مورد آزمایش قرار میگیرد
یک آزمایش سطح بالا ( high level ) به شمار میرود
ممکن است طولانی باشد
عموما به صورت دستی یا توسط یک سری اسکریپت اجرا میشود
مثال : گزارش ماهیانه باید جمع صحیحی از تمام صفحات را در آخرین برگه گزارش به همراه داشته باشد
ادامه دارد...
یازده. در جاوا رویدادها با استفاده از اینترفیسها پیاده سازی میشوند. برای نامگذاری یک رویداد، قاعده آن در جاوا بدین شکل است که نامها به صورت (+ ) Camel نوشته شده و آخرین عبارت هم Listener باشد و نیازی هم به حرف I در نامگذاری اینترفیس نیست؛ چون همه میدانند که این Listener آخری یعنی رویدادی که با اینترفیس پیاده سازی شده است و استفاده از I بی معنی است. هر چند بر خلاف دات نت، در اینجا استفاده از قاعده I چندان متداول نیست.
public interface CopyFileListener { void PublishProgress(long fileSize,long copiedSize); }
دوازده. گوگل اینترفیسهایی را که برای رویدادها میسازد، داخل کلاس اصلی تعریف میکند. پس بهتر هست که شما هم همین روند را ادامه بدید و از این قاعده خارج نشوید. اگر خوب دقت کرده باشید، در برنامه نویسی اندروید تمام اینترفیسها داخل کلاس اصلی هستند:
textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });
public class MemoryWare { public interface CopyFileListener { void PublishProgress(long fileSize,long copiedSize); } .... }
SetOnClickListener
editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } });
سیزده. آداپتورها و آداپتور ویوها (چون لیست) قسمت مهمی از برنامههای اندرویدی به شمار میآیند؛ تا حدی که در بیشتر برنامههای ساده هم حضور پررنگی دارند. ولی برای استفاده از این آداپتورها باید بدانید که نحوه کار آنها چگونه است. بسیاری از کاربران در این قسمت اشتباهات زیادی میکنند. اگر در stackOverflow هم در اینباره نگاه کنید، با حجم انبوهی از سوالات روبرو میشوید و فقط به خاطر اینکه نحوه کارکرد آن را نمیدانند، به مشکل برخوردهاند.
کلاس BaseAdapter اصلیترین کلاس آداپتور هاست که بقیه از آن مشتق شدهاند و معروفترین مشتقات آن، کلاسهای CursorAdapter و ArrayAdapter هستند که امکانات بیس آداپتور را افزایش دادهاند.به عنوان مثال در کد پایین از ArrayAdapter استفاده شده است.
نحوه کار یک آداپتور بدین صورت است که متدی را به نام GetView با قابلیت override دارد که با هر تعداد آیتم موجود صدا زده میشود. ولی اگر تصور کنیم فقط چند صدهزار آیتم هم داشته باشیم، آیا واقعا اجرا میشود؟ جواب این سوال این است که با هر بار اسکرولی که شما میکنید آیتمهای بعدی ایجاد میشوند ولی باز این سوال پیش میآید که هر آیتم برای خود جداگانه تشکیل میشود؟ مطمئنا جواب خیر است. آداپتورها از سیستمی به نام ViewRecycler برای کش کردن آیتمهای ایجاد شده استفاده میکنند و با هر اسکرولی که انجام میشود آیتمهای بعدی از روی آیتمهای قبلی که قبلا از صفحه خارج شدهاند، ساخته میشوند و آیتمهای کش شده قبلی را با پارامتری با نام convertView به دست شما میرساند.
کد زیر را ببینید:
@Override public View getView(int position, View rowView, ViewGroup parent) { ViewHolder viewHolder=null; if(rowView==null) { // 1. Create inflater LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // 2. Get rowView from inflater rowView = inflater.inflate(R.layout.row_bank_group_list, parent, false); viewHolder=new ViewHolder(); viewHolder.txtGroupName=(TextView) rowView.findViewById(R.id.text_groupName); rowView.setTag(viewHolder); } else { viewHolder=(ViewHolder)rowView.getTag(); } viewHolder.txtGroupName.setText(getItem(position).getName()); viewHolder.txtGroupName.setTypeface(new FontSystem().get_General_Font(context)); viewHolder.txtGroupName.setTextColor(context.getResources().getColor(R.color.black)); return rowView; }
کلاس داخلی ViewHolder هم یک الگو برای عدم بررسی Viewهای داخل آن است که نیازی به یافتن و تبدیل مجدد آنها نداشته باشید. در این روش شیء، داخل خصوصیت tag آیتم قرار گرفته است و وقتی از کش برداشته شود، خاصیت تگ آن را میخوانیم و مستقیما مورد استفاده قرار میدهیم. در این حالت شما بهترین استفاده را از پردازشها و حافظه، میکنید.
چهارده. یکی از کارهایی را که قبل از کار کردن در یک مسیر فیزیکی باید انجام دهید این است که مطمئن باشید اجازه نوشتن در آن ناحیه را دارید یا خیر. در غیر اینصورت برنامه شما با خطای FC روبرو میشود و اجرای آن خاتمه مییابد. به همین دلیل اکثر برنامه نویسان از متد CanWrite در کلاس File استفاده میکنند. ولی در هنگام استفاده از این متد باید دقت داشته باشید که کلاس File فقط باید حاوی مسیر باشد و اسمی از فایل مربوطه در آن نباشد. دلیل هم آن است که این احتمال میرود اگر فایلی هم وجود نداشته باشد، مقدار false را به شما برگرداند. مثال زیر قرار است فایلی را در کارت حافظه بنویسید، ولی بررسی اجازه نوشتن در مسیر، اشتباه است:
File file=new File(sdcardPath,fileName); if(file.CanWrite()) { ..... }
File file=new File(sdcardPath); if(file.CanWrite()) { file=new File(sdcardPath,filePath); ..... }
پانزده. کارت حافظه خارجی: همه برنامه نویسان اندروید حداقل یکبار از کد زیر استفاده کرده اند:
Environment.getExternalStorageDirectory()
هر برنامهای که در اندروید نصب میشود در مسیر
/Data/Data
/Data/Data/Info.Dotnettips.MyApp
/** * it will returns sd path for you * <p> * <b>Required Permission: </b>android.permission.READ_EXTERNAL_STORAGE<br/> * </p> * @return */ public List<String> GetExternalMounts() { final List<String> out = new ArrayList<>(); String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; String s = ""; try { final Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } // parse output final String[] lines = s.split("\n"); for (String line : lines) { if (!line.toLowerCase(Locale.US).contains("asec")) { if (line.matches(reg)) { String[] parts = line.split(" "); for (String part : parts) { if (part.startsWith("/")) if (!part.toLowerCase(Locale.US).contains("vold")) if(new File(part).canWrite()) out.add(part); } } } } return out; }
شانزده. یکی از روشهای انتقال اطلاعات بین اکتیویتیها مختلف استفاده از Extras هاست که شما با تعیین یک نام یا کلید، اطلاعات مربوطه را ارسال و توسط همان کلید؛ اطلاعات را در اکتیویتی مقصد دریافت میکنید:
notesIntent.putExtra("PartyId", PartyId); startActivity(notesIntent);
PartyId=getIntent().getLongExtra("PartyId",0);
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false); i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE);
هفده. قواعد نامگذاری: برای نامگذاری متغیرها از قانون CamelCase استفاده میکنیم. ولی برای حالات زیر از روشهای دیگر استفاده میشود:
- برای ثابتها از حروف بزرگ و _ استفاده کنید.
- برای متغیرهای خصوصی از حرف m در ابتدای نام متغیر استفاده کنید.
- برای متغیرهای استاتیک از حرف s در ابتدای نام متغیر استفاده کنید.
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; }
هجده: قاعده نظم و ترتیب در importها توسط مستندات گوگل بدین شکل تعریف شده است:
- نام پکیجهای ارائه شده توسط گوگل
- نام پکیجهای ثالث
- نام پکیجهای موجود در java و javax
- پکیجهای موجود در پکیج اصلی
نوزدهم. مرتب سازی متدهای دسترسی یک کلاس: بسیار خوب است که همیشه کدهای ما نظم خاصی را داشته باشد تا پیگیریهای شخصی و تیمی در آن راحتتر صورت بگیرد. برای مثال در یک کلاس ابتدا متدهای public و سپس private قرار گیرند و الی آخر.
الگوی عمومی که برای کار با جاوا صورت گرفته است به شکل زیر میباشد:
public, protected, private,abstract, static, transient, volatile, synchronized, final, native.
ادیتور intelij شامل تنظمیاتی برای مرتب سازی کدهاست که در این مورد بسیار سودمند است. با طی کردن مسیر زیر میتوانید برای آن ترتیب اینگونه موارد را مشخص کنید.
Settings>Editor>Code Style>Arrangement
در تصویر بالا متدها به ترتیب متدهای دستری بین بلوکهای کامنت method start و method end قرار گرفته اند.
همچنین شامل گزینههای دیگری نیز میباشد که به نظرم فعال کردنشان بسیار خوب است. گزینه keep overridden methods together به شما کمک میکند تا متدهایی را که رونویسی میشوند، در کنار یکدیگر قرار بگیرند که برای کلاسهای اندرویدی مثل اکتیویتیها و فرگمنتها و ... بسیار خوب است. گزینه مفید دیگر Keep dependent methods together است که در دو حالت عمقی یا خطی متدهای وابسته (متدهایی که متدهای دیگر را در آن کلاس صدا میزنند) در کنار یکدیگر قرار میدهد و مابقی گزینهها، که بسیار سودمند هست. به هر حال هر قاعدهای را که برای خود انتخاب میکنید اگر در حالت پیش فرض نیست بهتر است در مستندات پروژه ذکر شود تا افراد دیگر سریعتر به موضوع پی ببرند.
قسمت بیستم. این مورد برای افراد تازه کار میباشد که تازه اندروید استادیو را باز کردهاند و مشغول کدنویسی میباشند. یکی از مواردی که در همان مرحله اول به آن برمیخورید این است که intellisense ادیتور به بزرگی و کوچکی حروف حساس است و تنها با حرف اول سازگاری دارد. برای تغییر این مسئله باید مسیر زیر را طی کنید:
Settings>Editor>Completion>Case-sensitive Completion>None
زبان برنامه نویسی Erlang
زبان Erlang در سال 1986 توسط شرکت Ericson سوئد به منظور استفاده در سرورهای switching تلفن ساخته شد. این زبان توسط تیمی به سرپرستی Joe Armstrong معرفی شد تا بتواند از برنامههای توزیعشده، مقاوم در برابر خطا، بلادرنگ و بیوقفه پشتیبانی کند. بعدها این زبان به شکل متنباز در اختیار عموم قرار گرفت. یکی از روشهای برنامه نویسی که توسط این برنامه میشه ازش استفاده کرد، روش تابعی (Functional Programming) هست. این روش قبلا وجود داشت و مدتی هم از مد افتاد، ولی با اومدن پردازندههای چند هسته ای استفاده از زبانهای برنامه نویسی که میشه با اونها تابعی نوشت از سر گرفته شد و حتی مایکروسافت در سال 2010 زبان برنامه نویسی #F رو معرفی کرد. یکی از قابلیتهای زبانهای تابعی سرعت اجرا شدن کدهای اونها هست که اونها رو از زبانهای امری مثل #C و Java جدا میکنه.
Scala هم یک زبان برنامه نویسی همه منظوره هست که ویژگی هایی رو از زبانهای برنامه نویسی شیء گرا داره و همچنین توسط اون میشه برنامه نویسی تابعی انجام داد. از اون به عنوان جانشینی برای جاوا یاد میکنند چون قابلتهای اضافه بر جاوا رو داره.
از جمله مفاهیم استفاده شده در فریم ورک AUA
طراحی دامنه محور (DDD) Domain Driven Design
Clean Architecture
Clean Code
Domain-driven design (DDD)
SOLID Principle
Code Refactoring
GRASP pattern
GRASP pattern امکان توسعهی نرم افزار به شکلی ساده و سریع
مبتنی بر اصول SOLID
طراحی پیمانه ای یا ماژولار
معماری لایه بندی شده
آدرس سایت فریم ورک AUA