این مواردی که فرمودید رو چک کردم، مشکل حل نشد.
اما فکر میکنم به خاطر این هست که دکمه Export من تو UpdatePanel هست، راهی وجود داره که بشه این مشکل رو حل کرد؟
private static string toPersianNumbersUsingReplace(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; return data .Replace("0", "\u06F0") .Replace("1", "\u06F1") .Replace("2", "\u06F2") .Replace("3", "\u06F3") .Replace("4", "\u06F4") .Replace("5", "\u06F5") .Replace("6", "\u06F6") .Replace("7", "\u06F7") .Replace("8", "\u06F8") .Replace("9", "\u06F9"); }
private static string toPersianNumbersUsingReplace(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; return toEnglishNumbers(data) .Replace("0", "\u06F0") .Replace("1", "\u06F1") .Replace("2", "\u06F2") .Replace("3", "\u06F3") .Replace("4", "\u06F4") .Replace("5", "\u06F5") .Replace("6", "\u06F6") .Replace("7", "\u06F7") .Replace("8", "\u06F8") .Replace("9", "\u06F9"); } private static string toEnglishNumbers(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; return data.Replace("\u0660", "0") //٠ .Replace("\u06F0", "0") //۰ .Replace("\u0661", "1") //١ .Replace("\u06F1", "1") //۱ .Replace("\u0662", "2") //٢ .Replace("\u06F2", "2") //۲ .Replace("\u0663", "3") //٣ .Replace("\u06F3", "3") //۳ .Replace("\u0664", "4") //٤ .Replace("\u06F4", "4") //۴ .Replace("\u0665", "5") //٥ .Replace("\u06F5", "5") //۵ .Replace("\u0666", "6") //٦ .Replace("\u06F6", "6") //۶ .Replace("\u0667", "7") //٧ .Replace("\u06F7", "7") //۷ .Replace("\u0668", "8") //٨ .Replace("\u06F8", "8") //۸ .Replace("\u0669", "9") //٩ .Replace("\u06F9", "9"); //۹ }
.Replace("\u0669", "9") //٩
.Replace('\u0669', '9') //٩
private static string toPersianNumbersUsingStringBuilder(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; var strBuilder = new StringBuilder(data); for (var i = 0; i < strBuilder.Length; i++) { switch (strBuilder[i]) { case '0': case '\u0660': strBuilder[i] = '\u06F0'; break; case '1': case '\u0661': strBuilder[i] = '\u06F1'; break; case '2': case '\u0662': strBuilder[i] = '\u06F2'; break; case '3': case '\u0663': strBuilder[i] = '\u06F3'; break; case '4': case '\u0664': strBuilder[i] = '\u06F4'; break; case '5': case '\u0665': strBuilder[i] = '\u06F5'; break; case '6': case '\u0666': strBuilder[i] = '\u06F6'; break; case '7': case '\u0667': strBuilder[i] = '\u06F7'; break; case '8': case '\u0668': strBuilder[i] = '\u06F8'; break; case '9': case '\u0669': strBuilder[i] = '\u06F9'; break; default: strBuilder[i] = strBuilder[i]; break; } } return strBuilder.ToString(); }
private static string toPersianNumbersUsingToCharArray(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; var letters = data.ToCharArray(); for (var i = 0; i < letters.Length; i++) { switch (letters[i]) { case '0': case '\u0660': letters[i] = '\u06F0'; break; // مانند قبل } } return new string(letters); }
private static string toPersianNumbersUsingStringCreate(string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; return string.Create(data.Length, data, (chars, context) => { for (var i = 0; i < data.Length; i++) { switch (context[i]) { case '0': case '\u0660': chars[i] = '\u06F0'; break; // مانند قبل } } }); }
public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action);
return string.Create(data.Length, data, (chars, context) => {});
برای طراحی گزارش شما میتوانید به سه روش این کار را انجام دهید.
1- طراحی در برنامه طراح گزارش
2- طراحی از داخل ویژوال استودیو
3- طراحی گزارش در زمان اجرا
برای شروع شما میتوانید نسخه آزمایشی این گزارشساز را دریافت کنید. تنها محدودیت این نسخه نمایش عبارت Demo در چاپ میباشد.
برنامه Designer را اجرا کنید. در صورتی که برای اولین بار است این برنامه را اجرا میکنید ابتدا باید رابط کاربری خود را انتخاب نمایید. نوار ابزار سمت چپ تمامی ابزارهای پرکاربرد طراحی گزارش را در اختیارتان قرار میدهد. ابزارهایی که در این بخش درباره آنها توضیح داده خواهد شد عبارتند از:
Header, Footer, Data, Page Header, Page Footer, Report Title, Report Summery
*به ابزارهای بالا Band گفته میشود.
Header , Footer :
همانطور که از نامشان پیداست در قسمت بالا و پایین بخشی از گزارش قرار میگیرند که برای استفاده در بالا و پایین بند Data میباشد. به عنوان مثال بند Header مناسب طراحی سرستونهای یک جدول میباشد و بند Footer هم جهت نمایش اطلاعات انتهایی یک جدول. ولی شما میتوانید با تنظیم خصوصیات هر بند رفتار و نمایش آنها را به طور کل تغییر دهید. نکته مثبت این گزارشساز این است که شما میتوانید بیش از یک واحد از هر بند را بر روی صفحه طراح خود قرار دهید، به عنوان مثال شما میتوانید دو بند Header داشته باشید که یکی در صفحات زوج و دیگری در صفحات فرد نمایش داده شود.
Data :
این بند جهت نمایش اطلاعات از منبع دادهها میباشد. به این معنا که به ازای هر سطر از دادهها یک بار این بخش نمایش داده میشود. تعداد دفعات نمایش این بند محدود به تعداد سطرهای منبع داده و یا اندازه صفحه و همچنین خصوصیت محدوده نمایش سطرها در یک صفحه میباشد.
Page Header , Page Footer :
این دو بند با توجه به نامشان جهت نمایش در بالا و پایین هر صفحه از گزارش میباشد. البته باز هم یادآور میشوم که با تغییر در خصوصیاتشان میتوانید رفتار و نحوه نمایش آنها را تغییر دهید.
Report Title :
این بند فقط در ابتدای گزارش نمایش داده خواهد شد.
Report Summery :
این بند بلافاصله بعد از اتمام گزارش نمایش داده خواهد شد.
مثال :
برای شروع در Designer یک گزارش جدید از نوع Blank Report ایجاد نمایید. سپس در پنل Dictionary بر روی New Item کلیک کرده و گزینه XML Data را انتخاب نمایید. با توجه به محل نصب گزارشساز وارد مسیر …\Bin\Data شده و فایلهای Demo.xsd و Demo.xml را برای قسمتهای مربوطه انتخاب نمایید. یک بار دیگر بر رو New Item کلیک کرده و گزینه New Data Source را انتخاب نمایید، از لیست ظاهر شده کانکشنی را که ایجاد کردهاید را انتخاب نمایید؛ نتیجه کار تا اینجا باید به صورت زبر باشد.
جدول Product را دراگ کرده و بر روی صفحه طراحی گزارش رها کنید. فرم Data ظاهر میشود این فرم را مطابق تصویر زیر تنظیم نمایید.
حال بر روی صفحه طراحی گزارش بندهای Header, Data, Footer مشاهده میشود؛ حال شما میتوانید با کلیک بر روی سربرگ Preview خروجی گزارش را ببینید.
توابع :
این گزارشساز دارای توابع بسیاری است که اکثر نیازهای شما را برطرف میکند به عنوان مثال تابع تبدیل عدد به حروف به زبان فارسی. همچنین شما میتوانید توابع خاص خود را ساخته و به صورت رفرنس به گزارش اضافه نمایید.
در این بخش ما از توابع موجود در گزارش استفاده خواهیم کرد. برای شروع بر روی کامپوننت Text در بند Footer زیر ستون UnitPrice دابل کلیک کرده تا فرم TextEditor ظاهر شود. سربرگ Summery را انتخاب نمایید. مطابق اطلاعات زیر بخشها را تنظیم نمایید.
Summery Function: Sum
Data Band: DataProducts
Data Column: Products.UnitPrice
حال بر روی سربرگ Preview
کلیک نمایید تا خروجی گزارش را ببینید. جمع ستون UnitPrice
فقط در صفحه آخر نمایش داده خواهد شد. اگر بخواهید جمع ستون در پایین هر صفحه
نمایش داده شود ابتدا باید خصوصیت Print on All Pages بند Footer به True
ست شود. سپس بر روی کامپوننت Text در بند Footer،
دابل کلیک نمایید و در فرم TextEditor
سربرگ Summery
تیک Running Total
را به حالت انتخاب شده در بیاورید، حال خروجی گزارش را ببینید، جمع در انتهای هر
صفحه ظاهر میشود.
متغیرها :
در این گزارش ساز دو نوع متغیر وجود دارد؛ نرمال و سیستمی. نوع سیستمی شامل متغیرهایی میشود که کاربرد مشخصی در تهیه گزارش دارند، مثل شماره صفحه، شماره ردیف، عنوان گزارش و ...
برای مثال شما میتوانید متغیر سیستمی Line را برای روی صفحه طراحی دراگ کنید. دو کامپوننت Text بر روی صفحه ایجاد میشود. اولی با محتوای Line و دومی با محتوای {Line}. اولی را به بند Header و دومی را به بند Data منتقل کنید و سپس خروجی گزارش را مشاهده نمایید، حال گزارش شما دارای شماره ردیف است.
متغیرهای نرمال تقریبا همانند متغیرهایی هستند که همه روزه شما در برنامههای خود از آنها استفاده میکنید. با کلیک بر روی New Item گزینه New Variable را انتخاب نمایید و نوع متغیر را Decimal انتخاب نمایید، سپس متغیر ایجاد شده را دراگ کرده و بروی صفحه طراحی قرار دهید و مشابه متغیر Line عمل کرده و کامپوننتهای Text را در بندهای مناسب قرار دهید. سپس بند Data بر روی صفحه طراحی را انتخاب نمایید، در پنل Properties بر روی Eventes کلیک کرده سپس در رویداد Rendering کد زیر را وارد نمایید.
Variable1 += Products.UnitPrice
حال در خروجی گزارش میتوانید مقادیر محاسبه
شده را ببینید. توجه داشته باشید که شما میتوانید در رویدادهای این گزارشساز به
زبان VB
و C#
برنامه نویسی کنید و محدود به یک خط کد نمیباشید.
شما میتوانید گزارش ساخته شده را به صورتهای مختلف ذخیره کنید از جمله کد C# و یا یک اپلیکیشن قابل اجرا.
services.AddMvc();
app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });
namespace Razor { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //app.Run(async (context) => //{ // await context.Response.WriteAsync("Hello World!"); //}); } } }
namespace Razor.Models { public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { set; get; } } }
namespace Razor.Controllers { public class HomeController : Controller { // GET: /<controller>/ public ViewResult Index() { Product myProduct = new Product { ProductID = 1, Name = "Kayak", Description = "A boat for one person", Category = "Watersports", Price = 275M }; return View(myProduct); } } }
@model Razor.Models.Product @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width"/> <title>Index</title> </head> <body> Content will go here </body> </html>
@model Razor.Models.Product @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width"/> <title>Index</title> </head> <body> @Model.Name </body> </html>
@using Razor.Models
@model Product @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width"/> <title>Index</title> </head> <body> @Model.Name </body> </html>
@{ Layout = null; }
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> </head> <body> <div> @RenderBody() </div> </body> </html>
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <style> #mainDiv { padding: 20px; border: solid medium black; font-size: 20pt } </style> </head> <body> <h1>Product Information</h1> <div id="mainDiv"> @RenderBody() </div> </body> </html>
@model Product @{ Layout = "_BasicLayout"; ViewBag.Title = "Product"; }
@{ Layout = "_Layout"; }
@{ Layout = "_BasicLayout"; }
@model Product @{ ViewBag.Title = "Product"; }
کامپوننت |
انجام میشود |
انجام نمیشود |
Action Method |
یک شیء ViewModel را به View ارسال میکند. |
یک فرمت داده را به View ارسال میکند. |
View |
از شیء ViewModel برای ارائه محتوا به کاربر استفاده میکند. |
هر جنبهای از شیء View Model مشخصات را تغییر میدهد. |
*@ @model Product @{ ViewBag.Title = "Product"; } <p>Product Name: @Model.Name</p> <p>Product Price: @($"{Model.Price:C2}")</p>
<p>Product Name: @Model.Name</p>
using Microsoft.AspNetCore.Mvc; using Razor.Models; namespace Razor.Controllers { public class HomeController : Controller { // GET: /<controller>/ public ViewResult Index() { Product myProduct = new Product { ProductID = 1, Name = "Kayak", Description = "A boat for one person", Category = "Watersports", Price = 275M }; return View(myProduct); } } }
<p>Product Name: @Model.Name</p> <p>Product Price: @($"{Model.Price:C2}")</p> <p>Stock Level: @ViewBag.StockLevel</p>
@model Product @{ ViewBag.Title = "Product"; } p>Product Name: @Model.Name</p> <p>Product Price: @($"{Model.Price:C2}")</p> <p>Stock Level: @ViewBag.StockLevel</p> <div data-productid="@Model.ProductID" data-stocklevel="@ViewBag.StockLevel"> <p>Product Name: @Model.Name</p> <p>Product Price: @($"{Model.Price:C2}")</p> <p>Stock Level: @ViewBag.StockLevel</p> </div>
<div data-productid="1" data-stocklevel="2"> <p>Product Name: Kayak</p> <p>Product Price: £275.00</p> <p>Stock Level: 2</p> </div>
@model Product @{ ViewBag.Title = "Product Name"; } <div data-productid="@Model.ProductID" data-stocklevel="@ViewBag.StockLevel"> <p>Product Name: @Model.Name</p> <p>Product Price: @($"{Model.Price:C2}")</p> <p>Stock Level: @switch (ViewBag.StockLevel) { case 0:@:Out of Stock break; case 1: case 2: case 3: <b>Low Stock (@ViewBag.StockLevel)</b> break; default: @: @ViewBag.StockLevel in Stock break; } </p> </div>
<b>Low Stock (@ViewBag.StockLevel)</b>
using System; using PdfRpt; using PdfRpt.Core.Contracts; using PdfRpt.Core.Helper; using PdfRpt.FluentInterface; namespace PdfReportSamples.AdHocColumns { public class AdHocColumnsPdfReport { public IPdfReportData CreatePdfReport() { return new PdfReport().DocumentPreferences(doc => { doc.RunDirection(PdfRunDirection.RightToLeft); doc.Orientation(PageOrientation.Portrait); doc.PageSize(PdfPageSize.A4); doc.DocumentMetadata(new DocumentMetadata { Author = "Vahid", Application = "PdfRpt", Keywords = "Test", Subject = "Test Rpt", Title = "Test" }); }) .DefaultFonts(fonts => { fonts.Path(AppPath.ApplicationPath + "\\fonts\\irsans.ttf", Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf"); }) .PagesFooter(footer => { footer.DefaultFooter(printDate: DateTime.Now.ToString("MM/dd/yyyy")); }) .PagesHeader(header => { header.DefaultHeader(defaultHeader => { defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png"); defaultHeader.Message("گزارش جدید ما"); }); }) .MainTableTemplate(template => { template.BasicTemplate(BasicTemplate.SilverTemplate); }) .MainTablePreferences(table => { table.ColumnsWidthsType(TableColumnWidthType.Relative); }) .MainTableDataSource(dataSource => { dataSource.GenericDataReader( providerName: "System.Data.SQLite", connectionString: "Data Source=" + AppPath.ApplicationPath + "\\data\\blogs.sqlite", sql: @"SELECT [url] as 'آدرس', [name] as 'نام', [NumberOfPosts] as 'تعداد مطالب', [AddDate] as 'تاریخ ارسال' FROM [tblBlogs] WHERE [NumberOfPosts]>=@p1", parametersValues: new object[] { 10 } ); }) .MainTableSummarySettings(summary => { summary.OverallSummarySettings("جمع کل"); summary.PreviousPageSummarySettings("نقل از صفحه قبل"); summary.PageSummarySettings("جمع صفحه"); }) .MainTableAdHocColumnsConventions(adHocColumns => { //We want sum of the int columns adHocColumns.AddTypeAggregateFunction( typeof(Int64), new AggregateProvider(AggregateFunction.Sum) { DisplayFormatFormula = obj => obj == null ? string.Empty : string.Format("{0:n0}", obj) }); //We want to dispaly all of the dateTimes as ShamsiDateTime adHocColumns.AddTypeDisplayFormatFormula( typeof(DateTime), data => { return PersianDate.ToPersianDateTime((DateTime)data); } ); adHocColumns.ShowRowNumberColumn(true); adHocColumns.RowNumberColumnCaption("ردیف"); }) .MainTableEvents(events => { events.DataSourceIsEmpty(message: "There is no data available to display."); }) .Export(export => { export.ToExcel(); export.ToXml(); }) .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\AdHocColumnsSampleRpt.pdf")); } } }
SELECT [url] as 'آدرس', [name] as 'نام', [NumberOfPosts] as 'تعداد مطالب', [AddDate] as 'تاریخ ارسال' FROM [tblBlogs] WHERE [NumberOfPosts]>=@p1
adHocColumns.ShowRowNumberColumn(true); adHocColumns.RowNumberColumnCaption("ردیف");
adHocColumns.AddTypeDisplayFormatFormula( typeof(DateTime), data => { return PersianDate.ToPersianDateTime((DateTime)data); } );
adHocColumns.AddTypeAggregateFunction( typeof(Int64), new AggregateProvider(AggregateFunction.Sum) { DisplayFormatFormula = obj => obj == null ? string.Empty : string.Format("{0:n0}", obj) });
PM> Install-Package Lex.Db
public class Product { public int Id { get; set; } public string Name { get; set; } } public class Customer { public int Id { get; set; } public string Name { get; set; } public string City { get; set; } } public class Order { public int Id { get; set; } public int? CustomerFK { get; set; } public int[] ProductsFK { get; set; } }
public static class Database { public static DbInstance Instance { get; private set; } public static DbTable<Product> Products { get; private set; } public static DbTable<Order> Orders { get; private set; } public static DbTable<Customer> Customers { get; private set; } /// <summary> /// سازنده استاتیکی که در طول عمر برنامه فقط یکبار اجرا میشود /// </summary> static Database() { createDb(); getTables(); } private static void getTables() { Products = Instance.Table<Product>(); Customers = Instance.Table<Customer>(); Orders = Instance.Table<Order>(); } private static void createDb() { Instance = new DbInstance(Path.Combine(Environment.CurrentDirectory, "LexDbTests")); Instance.Map<Product>() .WithIndex("NameIdx", x => x.Name) .Automap(i => i.Id, true); Instance.Map<Order>() .Automap(i => i.Id, true); Instance.Map<Customer>() .WithIndex("NameIdx", x => x.Name) .WithIndex("CityIdx", x => x.City) .Automap(i => i.Id, true); Instance.Initialize(); } }
private static void addData() { var customer1 = new Customer { Name = "customer1", City = "City1" }; var customer2 = new Customer { Name = "customer2", City = "City2" }; Database.Instance.Save(customer1, customer2); // automatic Id assignment after Save var product1 = new Product { Name = "product1" }; var product2 = new Product { Name = "product2" }; Database.Instance.Save(product1, product2); // automatic Id assignment after Save var order1 = new Order { CustomerFK = customer1.Id, ProductsFK = new[] { product1.Id } }; var order2 = new Order { CustomerFK = customer2.Id, ProductsFK = new[] { product1.Id, product2.Id } }; Database.Instance.Save(order1, order2); // automatic Id assignment after Save }
private static void loadAll() { var orders = Database.Orders.LoadAll(); foreach (var order in orders) { // نحوه دریافت اطلاعات مشتری بر اساس کلید خارجی ثبت شده var orderCustomer = Database.Customers.LoadByKey(order.CustomerFK.Value); Console.WriteLine("Order Id: {0}, Customer: {1} ({2}) {3}", order.Id, orderCustomer.Name, orderCustomer.Id, orderCustomer.City); // نحوه بازیابی لیستی از اشیاء مرتبط از طریق آرایهای از کلیدهای خارجی ثبت شده var orderProducts = Database.Products.LoadByKeys(order.ProductsFK); foreach (var product in orderProducts) { Console.WriteLine(" Product Id: {0}, Name: {1}", product.Id, product.Name); } } }
private static void queryingByAnIndex() { var name = "customer1"; var customersList = Database.Customers .IndexQueryByKey("NameIdx", name) .ToList(); foreach (var person in customersList) { Console.WriteLine(person.Name); } }
// Using Take and Skip var list1 = Database.Orders.Query<int>() // primary idx .Take(1).Skip(2).ToList(); // Querying Between Ranges var list2 = Database.Customers .IndexQuery<string>("NameIdx") .GreaterThan("a", orEqual: true).LessThan("d").ToList();
private static void deletingRecords() { Database.Customers.DeleteByKey(key: 1); var customers = Database.Customers.LoadByKeys(new[] { 1, 2 }); Database.Customers.Delete(customers); }
public enum CustomerType { Person = 0, Company = 1 } public class Customer { public CustomerType Type { get; set; } }
با وجود چنین کلاسی از مشتری و نیاز به انجام فعالیتهای مختلفی بر روی آن، احتمالا نیاز خواهد بود که در بخشهای مختلف کد، گذارهی switch ای مانند زیر را اضافه کنید:
switch (customer.Type) { case CustomerType.Person: // calculate discount, or send message or edit customer or anything else break; case CustomerType.Company: // calculate discount, or send message or edit customer or anything else break; default: throw new ArgumentOutOfRangeException(); }
برای انجام فعالیتهای مختلفی مانند محاسبه تخفیف، ارسال پیام و یا ویرایش مشتری، نیاز خواهد بود این گذاره تکرار شود که خود این موضوع بوی بد duplicate code است و به الگوی shotgun surgery نیز ختم خواهد شد.
حال فرض کنید نیاز است مشتریان حقوقی، خود به دو نوع مشتری حقوقی بخش خصوصی و مشتری حقوقی بخش دولتی تقسیم شوند. در پیاده سازی ذکر شده باید به CustomerType یک آیتم افزوده شود و در تمامی switchها نیز در صورت نیاز شرط مربوط به آن اضافه شود.
برای حل این نوع از کد بد بو، معمولا یک کلاس پدر را به نام مشتری ایجاد کرده و کلاسهای مختص هر یک از انواع مشتری را از آن به ارث میبرند (Replace type code with subclass):
یا میتوان طراحی را کمی متفاوتتر و به صورت زیر انجام داد:
دلیل مشابه دیگر ایجاد این الگوی بد کد استفاده از type code به عنوان وضعیت یک تایپ است. که در این صورت میتوان بجای type code از state object استفاده کرد (Replace type code with strategy). به این مورد در مباحث مربوط به refactoring به طور مفصل پرداخته شده است.
این کد بد بو در شرایط متفاوتی ایجاد میشود. با این حال یکی از پر تکرارترین آنها استفاده بد یا عدم استفاده از الگوهای طراحی شیء گرا است. تصحیص این الگوی بد، به خوانایی و نگهداری کد در بلند مدت کمک بسیار زیادی میکند.