воскресенье, 27 февраля 2011 г.

MySQL и C#: Проблема с русскими буквами при сохранении в таблицу

Наверное это самая популярная проблема в MySQL – при сохранении русского текста в таблицу, текст стает таким вот: «?????? ??????!». Т.е все русские буквы преобразовываются в знаки вопроса, что говорит о проблеме кодировок.

MySQL C# Text Encoding Problems

Самым популярным решением этой проблемы было выполнить следующий запрос для установки необходимой кодировки после подключения:
SET NAMES utf8

Это и у меня работало в Perl и PHP, а вот в C# – не сработало.
И тут-то пошли извращения, дошло даже до такого:

string UtfConv(string strToConvert)
{
return System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Default.GetBytes(strToConvert));
}


Хорошо, что этот способ не сработал.
А оказалось, что стоит лишь немного подправить ConnectionString, указав в нем заветную кодировку:

И MySQL ConnectionString превращается…:
"server=localhost;uid=root;pwd=root;database=deeprss "

… превращается в следующий:
"server=localhost;uid=root;pwd=root;database=deeprss;charset=utf8"


Параметр я вычитал тут:
21.2.6. Connector/NET Connection String Options Reference


Все таблицы в БД у меня в utf8.

пятница, 4 февраля 2011 г.

C# code snipped: Create Excel instance using the dynamic keyword

The code below creates dynamic Excel.Application object without referencing the Excel COM server dll.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

dynamic excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
excel.Visible = true;
Console.Read();

}
}
}

понедельник, 31 января 2011 г.

I am working on DeepRSS



Тайна, покрытая мраком...

четверг, 27 января 2011 г.

Почему следует избегать специализации обобщений для базовых классов и интерфейсов в C#

За этой статьей стоит одна бессонная ночь, проведенная в холодном дебагере Вижуалстудии. Я совершил ошибку. Интересную ошибку, которой спешу поделиться.

Речь пойдет об обобщениях в C#, их конкретизации и о том, что иногда не стоит доверять ни компилятору, ни собственному интеллекту, а просто не наследовать от мухи слона, заводя огромное количество ненужных абстракций.

Длинная вводная



Для начала, давайте определимся с понятиями.

Под Обобщениями я подразумеваю общие (или параметризованные) типы в языке C#. В англоязычной литературе они называются Generics. Более подробно про обобщения можно прочитать тут: Обобщения (Глава из книги “Язык программирования C# 2005 (Си Шарп) и платформа .NET 2.0”)

Под специализацией обобщения, чтобы не начинать словоблудие, я понимаю вот это:

static void PrintAllItems<T>(T collection) where T:IEnumerable
{
// foreach работает медленно, зато универсально
foreach (var item in collection)
{
Console.WriteLine("IEnumerable: " + item.ToString());
}
}

static void PrintAllItems(int[] intCollection)
{
// for работает быстрее foreach
for (int i = 0; i < intCollection.Length; i++ )
{
Console.WriteLine("int: " + intCollection[i]);
}
}
Метод PrintAllItems(T collection) - это обобщенный метод.
Метод PrintAllItems(int[] intCollection) – это специализация обобщеного метода.

И теперь, метод PrintAllItems будет работать для всех IEnumerable – типов одинаково, кроме типа int[], для которого метод будет работать немного иначе (хотя, int[] точно также реализует IEnumerable как и double):

static void Main(string[] args)
{
double[] doubleArray = { 1.1, 2.2, 3.3};
int[] intArray = { 1, 2, 3 };

PrintAllItems(doubleArray);
PrintAllItems(intArray);
}


Результат:
IEnumerable: 1.1
IEnumerable: 2.2
IEnumerable: 3.3
int: 1
int: 2
int: 3

И наконец-то, почему же таки следует избегать конкретизации обобщений для базовых классов и интерфейсов
Чем проще писать программисту код, используя такие синтаксические сладости, как перегрузки методов и обобщения, тем сложнее компилятору разрешать эти самые перегрузки. Ведь практически каждый обобщенный метод может соответствовать любому типу. Может получиться так, что приложение будет работать очень странно. Тут все зависит от вашей осторожности… или неосторожности. Именно вы (и я в том числе), ответственны за создание методов, которые, не должны… должны создавать минимальное, замешательство для программиста, использующего ваш код и для вас самих.
Будьте осторожны. Ваши обобщенные методы могут быть более обобщение того, чего от них ожидают.
Да, ваши обобщенные методы могут быть неожиданно универсальны, и поверьте, что это не всегда хорошо.

Давайте рассмотрим следующий пример. А пока вы читаете код, постарайтесь угадать, что и в какой последовательности он выведет на экран.


using System;
namespace ConsoleApplication6
{
public class MyAnimalBase
{
}
public interface ISayableAnimal
{
void Say();
}
public class MyCatDerived : MyAnimalBase, ISayableAnimal
{
#region ISayableAnimal Members
void ISayableAnimal.Say()
{
Console.WriteLine("Inside MyCatDerived.Say");
}
#endregion
}
public class AnotherCow : ISayableAnimal
{
#region ISayableAnimal Members
public void Say()
{
Console.WriteLine("Inside AnotherCow.Say");
}
#endregion
}
class Program
{
static void WriteMessage(MyAnimalBase b)
{
Console.WriteLine("Inside Say(MyAnimalBase)");
}
static void WriteMessage<T>(T obj)
{
Console.Write("Inside Say<T>(T): ");
Console.WriteLine(obj.ToString());
}
static void WriteMessage(ISayableAnimal obj)
{
Console.Write(
"Inside Say(ISayableAnimal): ");
obj.Say();
}
static void Main(string[] args)
{
MyCatDerived d = new MyCatDerived();
Console.WriteLine("01 Calling Program.Say");
WriteMessage(d);

Console.WriteLine();
Console.WriteLine(
"02 Calling through ISayableAnimal interface");
WriteMessage((ISayableAnimal)d);

Console.WriteLine();
Console.WriteLine("03 Cast to base object");
WriteMessage((MyAnimalBase)d);

Console.WriteLine();
Console.WriteLine("04 Another Type test:");
AnotherCow anObject = new AnotherCow();
WriteMessage(anObject);

Console.WriteLine();
Console.WriteLine("05 Cast to ISayableAnimal:");
WriteMessage((ISayableAnimal)anObject);
}
}
}

И вывод будет следующим:
01 Calling Program.Say
Inside Say(T): ConsoleApplication6.MyCatDerived

02 Calling through ISayableAnimal interface
Inside Say(ISayableAnimal): Inside MyCatDerived.Say

03 Cast to base object
Inside Say(MyAnimalBase)

04 Another Type test:
Inside Say(T): ConsoleApplication6.AnotherCow

05 Cast to ISayableAnimal:
Inside Say(ISayableAnimal): Inside AnotherCow.Say

По себе знаю, уважаемый читатель, что вы, скорее всего не бросились анализировать скучный код, сопоставляя его с результатом выполнения.
Давайте разберемся вместе, что же все-таки произошло.
Первый тест показывает, и это очень важно запомнить, то, что WriteMessage(T obj) лучше соответствует типу, чем WriteMessage(MyAnimalBase b), для объекта, который унаследован от MyAnimalBase. Это потому, что компилятор идет по пути наименьшего сопротивления, и создает метод, который абсолютно соответствует типу MyCatDerived, превращая T в MyCatDerived.
А вот метод WriteMessage(MyAnimalBase b) требует преобразования типа. Это сложнее для компилятора, а значит -- WriteMessage(T obj) лучше.

Но, давайте отойдем от абстрактных примеров с животными и используем пример с IQueryable, который, как вам известно наследуется IEnumerable. Как вы думаете, победит ли Say(IEnumerable enumerable) хотя бы раз?




static void Say<T>(T obj)
{
Console.WriteLine("Say<T> won!!!");
}

static void Say(IEnumerable enumerable)
{
Console.WriteLine("IEnumerable won!!!");
}

static void Main(string[] args)
{
int[] a = {1, 2, 3};

IQueryable q = a.AsQueryable();

Say(a);
Say(q);
}


Нет. Не победит.
Say won!!!
Say won!!!


Именно это и было причиной моей бессонной ночи, о которой я упомянул вначале статьи. Но, вернемся к нашим барана…, то есть животным.

Следующие тесты показывают, что поведение компилятора можно все-таки контролировать путем явного приведение типа к интерфейсу или базовому классу.
Разрешение имен – это тема очень интересная. Только, к сожалению, бой между интеллектом программиста и компилятором всегда выиграет компилятор.

А победа на войне – за нами!

По мотивам книги «More Effective C# 50 Specific Ways to Improve Your C#»
Глава: Item 7. Do Not Create Generic Specialization on Base Classes or
Interfaces

понедельник, 24 января 2011 г.

31 день с Silverlight :: День #1: События мыши в Silverlight

Полный список англоязычный постов, вы можете найти тут: 31 Days of Silverlight Series = Awesome!


Оригинал англоязычного поста: Day #1: Mouse Events in Silverlight

В своем первом посте «31 день с Silverlight», мы сосредоточимся на обработчиках событий мыши. В случае интерактивных приложений, вы всегда желаете знать, когда пользователи работают с вашим приложением при помощи мыши. Это руководство расскажет о различных событиях мыши, и о том, как их использовать. Итак, давайте же сделаем первый шаг, на пути к освоению этой не сложной, но очень интересной темы


Событие MouseEnter


Я собираюсь продемонстрировать работу этого события на двух уровнях. Первым будет событие MouseEnter по всему Silverlight-контролу. Это событие будет возбуждено, когда курсор мыши входит в пространство, занимаемое Silverlight-контролом. Второе событие будет срабатывать при наведении мыши на круг, находящийся середине пользовательского контрола. Вот наш начальный XAML код.

<UserControl x:Class="SilverlightMouseEvents.MouseEnterDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
</Grid>
</UserControl>


Теперь я добавлю обработчики событий в XAML, и покажу вам, как сделать это в C# коде. Вот измененный XAML код вместе с добавленными обработчиками событий.

<UserControl x:Class="SilverlightMouseEvents.MouseEnterDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" MouseEnter="UserControl_MouseEnter">
<Grid x:Name="LayoutRoot" Background="White">
<Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" MouseEnter="myEllipse_MouseEnter" />
</Grid>
</UserControl>


Теперь нам необходимо перейти на code-behind файл кодом на C#, для реализации обработчика событий. Как только я создал обработчиков событий в XAML коде, студия автоматически создала для меня заготовки методов обработки событий в C# коде. Вот как выглядит первоначальное содержимое C# code-behind файла:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseEnterDemo : UserControl
{
public MouseEnterDemo()
{
InitializeComponent();
}

private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{

}

private void myEllipse_MouseEnter(object sender, MouseEventArgs e)
{

}
}
}


Для того, чтобы сохранить разумной длину этого поста, я не буду делать ничего сложного в моих обработчиках событий, но я покажу вам, как изменить цвет эллипса. Я добавил одну строку кода в каждый метод, и каждый из них закрашивает эллипс другим цветом. Сейчас, когда мы перемещаем курсор мыши в области Silverlight приложения — круг будет залит зеленым цветом, а когда курсор мыши окажется внутри круга — фигура будет закрашена пурпурным.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseEnterDemo : UserControl
{
public MouseEnterDemo()
{
InitializeComponent();
}

private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}

private void myEllipse_MouseEnter(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Purple);
}
}
}


Событие MouseLeave


Это событие работает практически точно также, как и событие MouseEnter. MouseLeave срабатывает тогда, когда курсор мыши ПОКИДАЕТ некую область. Что еще можно сюда добавить, а? На этот раз, однако, я вообще не делал изменений в моем XAML коде. Так вот, еще раз привожу начальный XAML код.

<UserControl x:Class="SilverlightMouseEvents.MouseLeaveDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
</Grid>
</UserControl>


На этот раз я сделаю все в C#-коде. Я добавлю обработчики событий в момент инициализации приложения. Вот мое окончательное решение на C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeaveDemo : UserControl
{
public MouseLeaveDemo()
{
InitializeComponent();
this.MouseLeave += new MouseEventHandler(MouseLeaveDemo_MouseLeave);
myEllipse.MouseLeave += new MouseEventHandler(myEllipse_MouseLeave);
}

void myEllipse_MouseLeave(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Purple);
}

void MouseLeaveDemo_MouseLeave(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}
}
}


Событие MouseLeftButtonDown


В этом случае, я продолжаю использовать тот же самый XAML код. Единственным изменением является ссылка на наш новый класс MouseLeftButtonDownDemo из XAML кода нашего юзер-контрола. Я уже показал, как использовать обработчики событий как в XAML, так и в C# коде. Вы уже видели XAML, так что я просто покажу только C# код.

Событие MouseLeftButtonDown, как вы уже догадались, срабатывает при нажатии левой кнопки мыши Пожалуйста, обратите внимание, что код этого примера так же охватывает пример события MouseLeftButtonUp, которое рассматривается ниже, и то, что значительной разницы между ними нет. Это будет особенно очевидно, когда мы займемся реализацией Drag & Drop. Вот пример добавления события MouseLeftButtonDown в наш код.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeftButtonDownDemo : UserControl
{
public MouseLeftButtonDownDemo()
{
InitializeComponent();
this.MouseLeftButtonDown += new MouseButtonEventHandler(MouseLeftButtonDownDemo_MouseLeftButtonDown);
myEllipse.MouseLeftButtonDown += new MouseButtonEventHandler(myEllipse_MouseLeftButtonDown);
}

void myEllipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}

void MouseLeftButtonDownDemo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Purple);
}
}
}


Событие MouseLeftButtonUp


До сих пор мы создавали отдельные методы-обработчики событий для каждого отдельного события. Во множестве случаев, вы обязательно захотите, чтобы разные элементы управления вызывали один и тот же метод обработки событий, чтобы каждый раз не писать один и тот же код обработки событий. В следующем примере, я добавлю еще один круг внутрь StackPanel. Обе эти фигуры будут менять свой фон на оранжевый. Вот наш новый, дополненный, XAML код:
<UserControl x:Class="SilverlightMouseEvents.MouseLeftButtonUpDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal" HorizontalAlignment="Center" >
<Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
<Ellipse x:Name="myEllipse2" Fill="Red" Width="150" Height="150" />
</StackPanel>
</UserControl>


Теперь мы добавим обработчик события MouseLeftButtonUp в нашем C# коде:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeftButtonUpDemo : UserControl
{
public MouseLeftButtonUpDemo()
{
InitializeComponent();
myEllipse.MouseLeftButtonUp += new MouseButtonEventHandler(Ellipse_MouseLeftButtonUp);
myEllipse2.MouseLeftButtonUp += new MouseButtonEventHandler(Ellipse_MouseLeftButtonUp);
}

void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Ellipse myCircle = sender as Ellipse;
myCircle.Fill = new SolidColorBrush(Colors.Orange);
}
}
}


Как видите, в теперь наш обработчик состоит из двух строк кода. Теперь нам необходимо получить ссылку на эллипс, который на самом деле вызвал метод-обработчик. Параметр «sender» содержит эту информацию, так что, с его помощью мы и получаем ссылку на эллипс, и заполняем фигуру необходимым цветом.

Событие MouseMove


В этом последнем примере, мы используем событие MouseMove. Это событие срабатывает каждый раз, когда курсор мыши меняет свои координаты. Вы можете контролировать перемещение мыши как по всей площади приложения, так и для конкретного элемента. В любом случае, вы можете сделать довольно много полезных вещей при помощи этого события, в том числе и реализовать перетаскивания элементов (Drag and Drop). (Drag and Drop мы рассмотрим в будущем посте).

Мой XAML настоящее время состоит из двух TextBox'ов на странице. Первый я, ловко, назвал Xbox, а второй — Ybox. Мы будем отображать новые X и Y координаты мыши в этих полях, каждый раз, в момент перемещения пользователем курсора мыши.

<UserControl x:Class="SilverlightMouseEvents.MouseMoveDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" VerticalAlignment="Center">
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBox x:Name="Xbox" Width="200" Height="35" Text="X" />
<TextBox x:Name="Ybox" Width="200" Height="35" Text="Y"/>
</StackPanel>
</UserControl>


Сейчас C# code behind файл выглядит не слишком сложными. В данном примере мы используем параметр MouseEventArgs, от которого мы получим текущие координаты мыши. После чего, просто запишем значения координат в текстовые поля.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseMoveDemo : UserControl
{
public MouseMoveDemo()
{
InitializeComponent();
this.MouseMove += new MouseEventHandler(MouseMoveDemo_MouseMove);
}

void MouseMoveDemo_MouseMove(object sender, MouseEventArgs e)
{
Xbox.Text = e.GetPosition(null).X.ToString();
Ybox.Text = e.GetPosition(null).Y.ToString();
}
}
}


Резюме


Это был краткий обзор событий мыши, которые доступны вам в Silverlight. Используя их вместе, можно создать очень интерактивный и динамичный интерфейс для пользователя. В завтрашнем посте, мы поговорим об интересных способах работы с экраном в Silverlight. И не только о возможности перехода с одного XAML файла на другой, но и о том, как реализовать PowerPoint-подобные переходы с одного экрана на другой.

< link > GlassDoor – сервис, на котором можно узнать про зарплаты в Google, Microsoft, Facebook, Yahoo

… И есть даже информация про Украинские компании, хотя, очень мало. Работа сайта базируется на анонимных анкетах пользователей. Можно оценить компанию, дать отзыв, рассказать о зарплате и.т.д. Такие анонимные анкеты, по моему субъективному мнению, могут быть довольно точными.

GlassDoor.com


суббота, 22 января 2011 г.

Неофициальная история конструирования ПО

В начале, был один ярус, и это было хорошо . В бородатых восьмидесятых, был один мейнфрейм и тысячи «немых» терминалов пользователей, которые были подключения к одной и только одной Большой Железяке. Эти 3270 терминалов называли «немыми», потому что у них была только клавиатура и монитор. Без процессора. Это было просто устройство ввода / вывода.


Два яруса . Благодаря Биллу Гейтсу, компьютеры, в комплекте с их собственными процессорами, ушли в массы, а в конце 80-х и начале 90-х я был разработки клиент-серверных приложений с "толстым клиентом" — часть расчетов осуществлялась на локальной машине, а данные находились в базе данных на уделенном сервере. Жизнь была легкой и простой. И резюме разработчиков были точно такими же легкими и простыми. Вам было только необходимо знать SQL для работы с данными и какой-нибудь язык программирования. Вот, например C++… Ах, Вам тяжело его изучить? Используйте SQLWindows, PowerBuilder, Visual Basic или даже Delphi!
Основной темой для обсуждения была: где реализовывать бизнес-логику — на стороне клиента или в базе данных, как набор хранимых процедур? В последнем случае, вы были вынуждены мастерски владеть процедурными языками СУБД, например, такими как T-SQL или PL/SQL. Но, больше от Вас ничего не требовалось.
Архитектура приложений по-прежнему оставалась простой. При запуске, приложение не требовало от вас подключения к Интернету, и это было хорошо. Приложения запускались на локальном компьютере, и работало в локальной сети. Конечно же, если сервер баз данных падал или слишком многие пользователи одновременно хотели получить данные, то в работе Вашего локального приложения могли бы возникнуть проблемы и перебои. Но, это было единственное узкое место, да и случалось такое не каждый день.

Три яруса. В середине девяностых годов, создание веб-браузеров, открыло Интернет для общественности. Предприятия с нетерпением переделывали их проверенные и надежные клиент-серверные системы для того, чтобы просто сделать их доступными в Интернете. Зачем? Потому что они могли это сделать. Именно с этого момента все начало усложнятся. Тонкий HTML клиент взаимодействовал веб-сервером, либо мог предоставлять статический контент (тексты, изображения), не используя для этого к помощи стороннего ПО, а при необходимости, можно легко передать управление на другой сервер для более продуктивной работы. Интернет провайдеры предлагали пропускную способность для продажи. Сетевые соединения были медленными. Тонкие клиенты выглядели очень плохо по сравнению с толстыми клиентами на Visual Basic или PowerBuider.
Вопрос остался прежним: «Где размещать бизнес-логику?» Уж точно не на тонком клиенте. Теперь выбор был либо где-то веб-сервере или в СУБД. Одного только веб-сервера уже было недостаточно. Так как я сам из мира Java, то хочу объяснить Вам, что же там происходило.

Множество ярусов . Средний ярус превратился в несколько уровней. Веб сервер взаимодействовал со Сервлет-контейнером, который в свою очередь взаимодействовал с контейнером EJB, который либо работал с СУБД непосредственно либо просто помещает сообщение в очередь Message-Oriented Middleware. Чтобы сделать это еще более гибким, добавьте в коктейль несколько служб контроля доступа, так чтобы Java сначала посмотрела туда, перед тем как поместить сообщение в очередь. Давайте не будем забывать и о демилитаризованных зонах (DMZ), которые увеличивают общее число ярусов.
Вот когда появилось Новое Поколение Разработчиков. Эти люди, называющие себя Архитекторами программного обеспечения. Они требовали чтобы логические слои были специфичны и заточены под разрабатываемый проект. И они хотели их сейчас! Книга по шаблонам проектирования от «банды четырех» была легко доступна, — и шабаш начался.

Это было время расцвета фреймворков для создания ПО.

Если разработчик Java не знал Struts в начале этого века, то его шансы быть нанятым для разработки Enterprise проектов были близки к нулю. Сейчас все больше и больше людей понимают, что Struts был еще одним недопеределанным бесполезным MVC фреймворком, который усложнял архитектуру тысяч приложений. Но само существование таких фреймворков получило теплый прием и даже овации в легионах быдлокодеров (Code monkey), которые поняли, что они могут зарабатывать на жизнь, вставляя if и else в шаблоны, предоставленные местными архитекторами. Заканчивать ВУЗ для получения диплома по компьютерным наукам уже не нужно.
Первое десятилетие 21-го века подходит к концу, и мы все еще живем в очень хрупком мире программного обеспечения с дести ярусными архитектурами. Каждый дополнительный уровень (как движущуюся часть) делает архитектуру еще более хрупкой. Каждая подвижная часть покупается с дополнительными расходами — технической поддержкой. Но в мутной воде многоуровневых архитектур, команды поддержки довольно быстро начинают играть в игру перевода стрелок друг на друга.
Бюджет первоначально выделенных на проект, получает опустошается довольно быстро, владелец проекта начинает урезать функционал для экономии средств, что оставляет ему несколько кое-как работающих приложений. Это здорово, что наши офшорные партнеры готовы протянуть руку помощи! Мы в ней нуждается. Это как присланные деньги от родителей для студента, живущего в общежитии.

Два яруса . Вот уже прошло две недели, как началось второе десятилетие 21-го века. Я очень надеюсь, что мы вернемся назад к двухуровневой архитектуре. Как же так? Клиенты взаимодействуют облаком, это и создает всего два яруса. Вы можете утверждать, что облако само по себе содержит несколько уровней внутри, но это все немного по другому. Облако может поддерживаться одним поставщиком, а с точки зрения клиента это единая часть программного обеспечения.

Приложение клиента запускается локально, оно имеет локальное хранилище, что позволяет работать как в онлайн, так и в офлайн режиме. И данных и код находятся настолько близко к пользователю, насколько это возможно. Вы думаете, почему Microsoft Excel является наиболее популярным программным обеспечением среди бизнес-пользователей на предприятиях? Потому что Excel позволяет пользователю иметь свой маленький кусочек данных и любительский, но рабочие код (формулы) очень близко. Прямо на рабочем столе. Нет необходимости просить этих Всемогущих Админов о милости и помощи. Нет зависимости от сетевого подключения или каких-то таинственных серверов, которые могут работать медленно или падать. Наиболее продвинутые пользователи даже научиться работать с базами данных MS Access, чтобы уменьшить зависимость от отдела IT. Так держать!


Рассмотрим пример автоматизации продаж. В настоящее время, наша компания работает над программным обеспечением, предназначенным для автоматизации работы страховых агентов. Я просто приведу один пример. Мы храним цифровые подписи клиентов в базе данных. Агент приходит в дом клиента, заполняет электронные формы и просит человека поставить подпись пальцем прямо по стеклу смартфона работающего под Android. Приложение на Adobe AIR сохраняет эту оцифрованную подпись в локальной базе данных смартфона. Как только агент сможет получить доступ к любой сети Wi-Fi, он сможет синхронизировать локальные данные с любым ПК или облаком. Разве это не в два яруса? Продавец может запустить и работать с приложением в независимости от наличия соединение с Интернетом. Когда соединение будет доступно, данные можно будет синхронизировать Уровнем 2. Вот и все. Клиент-Сервер вернулся.

Один ярус. Шансы довольно высоки, что через 10-15 лет мы снизим число уровней архитектуры обратно в один ярус превратить наши смартфоны в немые терминалы.
«Да, возможно я и мечтатель. Но я такой не один»
Джон Леннон


Оригинал: The Unofficial History of Software Engineering

Про эту замечательную статью я узнал из подкаста автора статьи Якова Файна (Будама). За что что ему спасибо. ;)

Если Вы хотите прослушать его комментарии к статье, то прошу Вас проследовать по ссылке ниже:
Америчка: #267 Неофициальная история конструирования ПО

Перевод статьи с английского на русский: Дмитрий Жарий

 

.NET ate my MOSK;. Powered By Blogger © 2009 Bombeli | Theme Design: ooruc