اگر طراح وب هستید، قطعا کمبود فونتهای مناسب فارسی برای استفاده در طرحهایتان را حس کردهاید و با مشکلات زیادی برای استفاده از فونتهای فعلی روبرو بودهاید. متنوع نبودن قلمهای موجود فارسی، سازگار نبودن بیشتر قلمهای موجود با وب، نمایش مشکلدار و پلهپله در صفحات وب، نمایش متفاوت در مرورگرهای مختلف، یکسان نبودن عملکرد و ظاهر قلم در سیستمعاملهای مختلف و … تنها تعدادی از مشکلات موجود هستند.
متغیرها در ES 6
اجرا شدن مثال اول با فایرفاکس به این معنا است که هنوز پیاده سازی استاندارد ES 6 در فایرفاکس، توابع قرار گرفتهی در یک block را block-scoped نمیداند (و این پیاده سازی هنوز ناقص است).
- وجود let به نوعی پیاده سازی مفهوم fail fast است. هر چه سریعتر مشکلات مشخص شوند، بهتر از این است که در آینده با گنگ بودن میدان دید متغیرها، مشکلات دیباگ برنامه بیشتر شوند.
معماری لایه بندی نرم افزار #1
پس از ایجاد پروژه جدید، یک ارجاع از Microsoft.Office.Interop.Word به پروژه خود اضافه میکنیم
در هنگام نصب مجموعه Office میتوانید یک چاپگر مجازی بنام Microsoft Office Document Image Writer را نصب کنید. میخواهیم از آن برای رسیدن به هدفمان استفاده کنیم.
حال یک فایل Word آماده میکنیم.
با استفاده از کدهای زیر میتوان فایل ذخیره شده را به یک فایل تصویری با قالب TIF تبدیل کنیم
private void btnPrint_Click(object sender, EventArgs e) { try { object varFileName = @"d:\test.doc"; object varFalseValue = false; object varTrueValue = true; object varMissing = Type.Missing; Microsoft.Office.Interop.Word.Application varWord = new Microsoft.Office.Interop.Word.Application(); varWord.ActivePrinter = "Microsoft Office Document Image Writer"; // varWord.ActivePrinter = "Snagit 11"; // varWord.ActivePrinter = "priPrinter"; // varWord.ActivePrinter = "doPDF v7"; Microsoft.Office.Interop.Word.Document varDoc = varWord.Documents.Open(ref varFileName, ref varMissing, ref varFalseValue,ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing); varDoc.Activate(); object PrintToFile = true; object OutputFileName = @"d:\test.tif"; varDoc.PrintOut(ref varMissing, ref varFalseValue, ref varMissing, ref OutputFileName, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref PrintToFile, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing, ref varMissing); varDoc.Close(ref varMissing, ref varMissing, ref varMissing); varWord.Quit(ref varMissing, ref varMissing, ref varMissing); } catch (Exception varE) { MessageBox.Show("Error:\n" + varE.Message, "Error message"); } }
varWord.ActivePrinter = "Snagit 11"; varWord.ActivePrinter = "priPrinter"; varWord.ActivePrinter = "doPDF v7";
برای پیاده سازی اینگونه ستونها SQL Server یک قابلیتی به نام computed column ارائه داده است. برای تعریف این چنین ستون هایی بعد از نام ستون از کلمه AS استفاده میکنیم. عبارتی که ستون محاسباتی را تشکیل میدهد میتواند شامل این موارد باشد: تابع، نام ستون غیر محاسباتی و مقادیر ثابت ولی امکان استفاده از subquery وجود ندارد.
ستونهای محاسباتی بطور پیشفرض مجازی هستند (بطور فیزیکی بر روی دیسک ذخیره نشده اند). یعنی هر موقع که query اجرا میشود آنها نیز مجدد محاسبه شده و نمایش داده میشوند.
برای اینکه نوع ذخیره سازی را از مجازی به فیزیکی تبدیل کنیم باید در هنگام ساخت جدول (یا تغییر آن) از کلید واژه PERSISTED استفاده کنیم. وقتی بطور فیزیکی ذخیره شده باشد با هر بار ویرایش یکی از ستونهای تشکلیل دهنده ستون محاسباتی هم ویرایش میشود.
ستون محاسباتی بعد از تبدیل شدن از مجازی به فیزیکی میتواند به عنوان کلید اولیه و ایندکس در نظر گرفته شود.
به مثال زیر توجه کنید:
جدولی داریم با دو ستون، قرار هست بر اساس ترکیب مقادیر دو ستون جستجویی انجام دهیم. ضمن اینکه ترکیب دو ستون باید منحصر بفرد باشد. برای این منظور یک unique index روی دو ستون لحاظ میکنیم.
create table t1 ( col1 char(1), col2 char(1) ) create unique nonclustered index ix_uq on t1 (col1 , col2); insert t1 values('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('E', 'F'), ('G', 'H'), ('I', 'J'), ('K', 'L'), ('M', 'N'), ('O', 'P');
اکنون به دنبال سطری میگردیم که ترکیب مقادیر دو ستون آن برابر با OP باشد. پس query زیر را اجرا میکنیم
select col1 + col2 from t1 where col1 + col2 = 'OP'
برای اینکه Index Seek داشته باشیم بایستی مقادیر را جداگانه مقایسه کنیم(ستونها به صورت عبارت محاسباتی نباشند)
select col1 + col2 from t1 where col1 = 'O' and col2 = 'P'
ولی ما میخواهیم شرط بر اساس ترکیب دو ستون باشد. خب اینجا هست که Computed Columns مطرح میشوند.
alter table t1 add col3 as col1 + col2 persisted create clustered index ix1 on t1 (col3)
حال مجددا عمل جستجو را انجام میدهیم ولی به کمک ستون محاسباتی که اخیرا ایجاد نمودیم:
select * from t1 where col3 = 'OP';
حالا مشاهده میشود که شاخص ix1 اسکن نشده است. و از آنجایی که شاخص از نوع Clustered است مشکل Covering هم نخواهیم داشت.
افزونه فارسی به پارسی را قبل از ارائه در سایت، بر روی یک ماشین مجازی هم تست کردم. برای این منظور از Microsoft virtual pc استفاده شد. البته در مقابل امکانات VMware شاید حرفی برای گفتن نداشته باشد ولی خوب جهت مقاصد تست نرم افزار بر روی یک سیستم عاری از وسایل برنامه نویسی مناسب است. (برای نصب یک سیستم عامل توسط آن برای مثال میشود از سی دی آن OS یک فایل ISO تهیه کرد و مسیر این فایل ISO را به ماشین مجازی معرفی کرد . سپس سیستم بوت شده و روال نصب مطابق معمول خواهد بود)
اولین مشکلی که پس از تست بر روی سیستم مجازی رخ داد، پیغام یافت نشدن اسمبلی مربوط به SQLite بود. نرم افزار word هنگام اجرای افزونههای دات نت، آنها را در مسیری با یک نامگذاری منحصربفرد کپی میکند و تنها هم همان اسمبلی افزونه را کپی میکند و نه سایر موارد همراه را. برای پیدا کردن این مسیر میشود از روش زیر استفاده کرد:
using System.Reflection;
Assembly.GetExecutingAssembly().Location
برای نصب اسمبلی در GAC استفاده از برنامه gacutil توصیه شده است. این برنامه به همراه SDK دات نت فریم ورک ارائه میشود و الزامی ندارد که کاربر نهایی این برنامه را داشته باشد. خوشبختانه با استفاده از برنامه نویسی هم میشود یک نمونه از برنامه Gacutil را خودمان ایجاد کنیم (برای مثال ایجاد یک برنامه کنسول و دریافت مسیر از طریق آرگومانهای ارسالی به آن):
new System.EnterpriseServices.Internal.Publish().GacInstall(path);
این روش در مورد اسمبلی SQLite که دارای امضای دیجیتال است کار خواهد کرد. اما اگر قصد داشته باشید به صورت عمومی از آن استفاده کنید، باید ابتدا بررسی کرد که آیا فایل اسمبلی دارای امضای دیجیتال است یا خیر. برای این منظور میتوان مقدار عبارت زیر را ارزیابی کرد:
Assembly.LoadFile(path).GetName().GetPublicKey().Length
لازم به ذکر است که متد معرفی شده برای نصب در GAC در صورت عدم موفقیت هیچ پیغام خطا یا exception ایی را در برنامه تولید نخواهد کرد. اما پیغام خطای حاصل را در event log ویندوز میتوان مشاهده کرد.
OVER ( [ <PARTITION BY clause> ] [ <ORDER BY clause> ] [ <ROW or RANGE clause> ] ) <PARTITION BY clause> ::= PARTITION BY value_expression , ... [ n ] <ORDER BY clause> ::= ORDER BY order_by_expression [ COLLATE collation_name ] [ ASC | DESC ] [ ,...n ] <ROW or RANGE clause> ::= { ROWS | RANGE } <window frame extent> <window frame extent> ::= { <window frame preceding> | <window frame between> } <window frame between> ::= BETWEEN <window frame bound> AND <window frame bound> <window frame bound> ::= { <window frame preceding> | <window frame following> } <window frame preceding> ::= { UNBOUNDED PRECEDING | <unsigned_value_specification> PRECEDING | CURRENT ROW } <window frame following> ::= { UNBOUNDED FOLLOWING | <unsigned_value_specification> FOLLOWING | CURRENT ROW } <unsigned value specification> ::= { <unsigned integer literal> }
CREATE TABLE REVENUE ( [DepartmentID] int, [Revenue] int, [Year] int ); insert into REVENUE values (1,10030,1998),(2,20000,1998),(3,40000,1998), (1,20000,1999),(2,60000,1999),(3,50000,1999), (1,40000,2000),(2,40000,2000),(3,60000,2000), (1,30000,2001),(2,30000,2001),(3,70000,2001)
select *, avg(Revenue) OVER (PARTITION by DepartmentID) as AverageRevenue, sum(Revenue) OVER (PARTITION by DepartmentID) as TotalRevenue from REVENUE order by departmentID, year;
insert into REVENUE values(1,90000,2002),(2,20000,2002),(3,80000,2002), (1,10300,2003),(2,1000,2003), (3,90000,2003), (1,10000,2004),(2,10000,2004),(3,10000,2004), (1,20000,2005),(2,20000,2005),(3,20000,2005), (1,40000,2006),(2,30000,2006),(3,30000,2006), (1,70000,2007),(2,40000,2007),(3,40000,2007), (1,50000,2008),(2,50000,2008),(3,50000,2008), (1,20000,2009),(2,60000,2009),(3,60000,2009), (1,30000,2010),(2,70000,2010),(3,70000,2010), (1,80000,2011),(2,80000,2011),(3,80000,2011), (1,10000,2012),(2,90000,2012),(3,90000,2012)
select Year, DepartmentID, Revenue, sum(Revenue) OVER (PARTITION by DepartmentID ORDER BY [YEAR] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) as Prev3 From REVENUE order by departmentID, year;
ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) as Prev3
select Year, DepartmentID, Revenue, sum(Revenue) OVER (PARTITION by DepartmentID ORDER BY [YEAR] ROWS BETWEEN CURRENT ROW AND 3 FOLLOWING) as Next3 From REVENUE order by departmentID, year;
select Year, DepartmentID, Revenue, min(Revenue) OVER (PARTITION by DepartmentID ORDER BY [YEAR] ROWS UNBOUNDED PRECEDING) as MinRevenueToDate From REVENUE order by departmentID, year;
RANGE UNBOUNDED PRECEDING AND CURRENT ROW
CREATE TABLE Employees ( EmployeeId INT IDENTITY PRIMARY KEY, Name VARCHAR(50), HireDate DATE NOT NULL, Salary INT NOT NULL ) GO INSERT INTO Employees (Name, HireDate, Salary) VALUES ('Alice', '2011-01-01', 20000), ('Brent', '2011-01-15', 19000), ('Carlos', '2011-02-01', 22000), ('Donna', '2011-03-01', 25000), ('Evan', '2011-04-01', 18500) GO
SELECT Name, Salary, AVG(Salary) OVER(ORDER BY HireDate) AS avgSalary FROM Employees GO
SELECT Name, Salary, AVG(Salary) OVER(ORDER BY HireDate RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS avgSalary FROM Employees GO
SELECT Name, Salary, AVG(Salary) OVER(ORDER BY HireDate RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS avgSalary FROM Employees GO
از جمله مفاهیم استفاده شده در فریم ورک AUA
طراحی دامنه محور (DDD) Domain Driven Design
Clean Architecture
Clean Code
Domain-driven design (DDD)
SOLID Principle
Code Refactoring
GRASP pattern
GRASP pattern امکان توسعهی نرم افزار به شکلی ساده و سریع
مبتنی بر اصول SOLID
طراحی پیمانه ای یا ماژولار
معماری لایه بندی شده
آدرس سایت فریم ورک AUA