Показаны сообщения с ярлыком программирование. Показать все сообщения
Показаны сообщения с ярлыком программирование. Показать все сообщения
0

О хорошем коде.

Сегодня к вечеру меня накрыл приступ графомании. И писать вроде хочется, и в то же время, особо не о чем: дом-работа-дом-работа-дом-работа-дача.... :)

Давно, лет 10 назад, на одном форуме, я увидел тему "Как не надо писать код". В противоположность ей я открыл тему "Как надо писать код". Через пару дней в первой теме было несколько страниц сообщений, а в моей - добавилось только одно или 2. После того случая я не раз замечал, что советов "как не надо" - очень много, а вот "как надо" - днем с огнем не сыщешь. Не пойму - это скромность или страх ответственности за свои слова? Полагаю, что второе, поскольку я еще не встречал программера, который бы публично признал себя.... ну пусть не тупым, но , скажем так, тугодумом :)

Посему я решил взять на себя ответственность сказать, каким должен быть хороший код и как его получить.

Признаки хорошего кода:
1. Хороший код не пребывает долго в неизменном состоянии, потому что он меняется. Именно из-за этого он и хорош - его легко менять, и если вдруг в программу нужно внести изменения, то (если есть такая возможность) проще их сделать в том месте, где их сделать проще :). Иначе говоря, хороший код - код, который легко дополнять и изменять в случае необходимости.
2. Вытекает из первого - хороший код понятен. Именно поэтому его менять легко, - не боишься чего-то поломать. Если не понимаешь, что и для чего делает код, но вносить изменения необходимо - ощущение такое, что движешься по минному полю. Такой код ужасен.

Ну вот пожалуй, и все признаки, остальное - вторично.

Теперь несколько конкретных приемов, облегчающих жизнь. Приемы применимы к объектно-ориентированным языкам с Си-подобным синтаксисом: C++, C#, Java.

1. Старайтесь в качестве параметра метода передавать интерфейс, а возвращать конкретный тип.
Вот это:
ArrayList foo(Map par);
в большинстве случаев лучше, чем вот это:
List foo(HashMap par);
Лучше по той причине, что наверняка избавит вас от необходимости явного приведения типов от базового к производному.
За исключением тех случаев, где метод может возвращать разные типы, производные от одного базового. Тут, естественно, нужно возвращать интерфейс или базовый класс.

2. Любая сущность должна быть тем, чем она выглядит, а не чем-то другим. Т.е. как минимум, переменную, по смыслу являющейся счетчиком, не стоит называть date или gender (нужно назвать counter), а переменную для хранения даты - не стоит называть counter (нужно назвать date).

3. Вместо синглтонов используйте static. Это в продолжение приема №2. В чем разница между синглтоном и static-классом (в C++ это может быть класс с приватным конструктором и исключительно static-полями и методами)? Имхо, только в том, что static-класс сразу показывает, что он есть на самом деле, в то время как синглтон притворяется обычным классом. Единственное исключение, которое мне приходит в голову, - это случай, когда экземпляр класса должен быть единственным, и при этом он обязан реализовать какой-то интерфейс (к примеру, экземпляр этого класса нужно передать в метод, принимающий экземпляры, реализующие этот интерфейс).

4. Не старайтесь делать "задел на будущее". Реализуйте только тот функционал, который необходим для решения заданной задачи, и ни в коем случае не больше. В моей практике еще не было случая, когда сделанный "про запас" функционал пригодился бы в будущем. В лучшем случае он безболезненно удалялся, в худшем - становился рудиментом, мешающим дальнейшему развитию проекта.

5. Ну и конечно, метод должен выполнять такие действия, которые можно сформулировать естественным языком. Написание метода лучше сразу начать с шапки-комментария, в котором будет описано, что метод делает, какие параметры принимает, и для чего они нужны. Если долго не получается написать такое описание, значит или метод должен быть не один. Очень способствует появлению у кода признака №1 :)

6. Вытекает из 5: методы должны быть короткими. Насколько? Должны целиком помещаться на экране. Аналогично 5 очень способствует появлению у кода признака №1 :)

7. Совет насчет классов: если есть трудности в понимании того, какие у класса должны быть методы и какие поля - нужно написать словесное описание того, что класс должен делать. После того, как написали - прочитайте написанное. Глаголы будут означать методы, необходимые классу, существительные - поля класса. Изредка существительные - это параметры, передаваемые в методы.

Все, графоманский зуд удовлетворен:) Можно идти спать :)

2

Преобразование из Image (System.Drawing.Image, Win Forms) в ImageSource (WPF)

Недавно понадобилось это сделать, поскольку в данный момент пишу на c# приложение, использующее как win forms, так и WPF. Кроме того, картинки у меня загружаются из потока (точнее, из БД).
Получилось не сразу, поэтому возможно, мои труды кому-нибудь пригодятся:

using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Media;
using System.Windows.Media.Imaging;
 
namespace ...
{
    class ...
    {
 
    public static ImageSource imageToImgSource(Image image)
    {
        using (var ms = new System.IO.MemoryStream())
        {
            image.Save(ms, ImageFormat.Png);
            var img_source = new BitmapImage();
            img_source.BeginInit();
            img_source.UriSource = null;
            img_source.CacheOption = BitmapCacheOption.OnLoad;
            img_source.StreamSource = ms;
            img_source.EndInit();
            return img_source;
        }
    }
 
    }
}
2

Странности мышления и бытия

Недавно думал о том, как мне порой удается находить баги в своих прогах. И поймал себя на ощущении, что я весь текст программы помню! Как правило, это 5-7 тыс. строк, редко больше, но и не меньше.

Еще хочу попросить прощения за свое долгое молчание у тех читателей, кто интересуется тем, что я пишу :) Давно ничего интересного не приходило в голову, наверно из-за того, что сменил работу. Заниматься какими-то своими идеями часто есть время, но нет желания. Не знаю почему... Когда я много работаю, у меня образуется какая-то пустота внутри... Ничего неохота делать. Точнее, ощущение такое, что если что-то начнешь, до конца довести все равно не получится, потому что сегодня у тебя есть свободное время(и довольно много), а потом его может не быть втечение нескольких недель, и даже выходные чем-то заняты (как правило, это ремонт квартиры).

Недавно опять приснился смешной сон, но я его не записал, а потому не запомнил. Но зато успел рассказать жене. Счас ее спросил, но она тоже его забыла. Интересно, мне иногда снятся смешные сны (редко, но бывает - это был второй). Гораздо чаще снятся страшные, но их хочется поскорее забыть и не хочется пересказывать.

А еще мне хочется рассказать кое-что про нашего кота. Кто не в курсе, его зовут Байт. Недавно он нас сильно напугал. Началось с того, что мы на балконе оставили землю в ящике для рассады, и он повадился туда ходить по-маленькому. Сначала мы этого не заметили, но через некоторое время характерная вонь на балконе дала знать о том, что коту ящик с землей очень понравился. Землю из ящика выкинули, ящик вымыли. Казалось бы, на этом все должно закончится. Но пришло время менять наполнитель в штатном туалете нашей лохмато-усатой единицы информации (мы использовали селикогелевый наполнитель, который почти не пах, посему его меняли раз в 2 недели). Мы были несколько удивлены тем, что в туалете нет (как бы это помягче выразиться... ) ну... какашек там не было, вот (кстати, почему слово "какашка" подчеркивается красным в редакторе??? а как еще "это" называть?)! Ну ладно, день нет, два нет... на четвертый день мы забеспокоились. Вдруг у зверя запор (не дай бог, механический - проглотил, бедняга, какую-то твердую бяку и придется его лечить). Но зверь играл, и, более того - кушал, как из пулемета, и куда все это из него девалось, было непонятно. Короче, пару дней мы эти самые штуки (в которые еда превращается в живых организьмах) искали по всей квартире, местами даже с фонариком. На балконе тоже глядели (местами - тоже с фонариком). Принюхивались. В конце концов сводили его к ветеринару, который сказал, что мы просто плохо искали, а у кота все хорошо :) В конце концов нашли дыру в балконной перегородке, через которую он (теоретически) мог пролезть к соседям и там вершить злодеяния. После чего отлучили зверя от балкона. И... О чудо! через день долгожданная субстанция появилась в кошачьем лотке.

Да! А еще жена просила всех поздравить с Днем Космонавтики! Вот, всех поздравляю, от нее и от себя тоже! :)
9

Знакомьтесь – Байт!

Вот такой зверь появился у нас примерно полтора месяца назад. Характер у него довольно вредный, очень не любит, когда ограничивают его свободу,  но очень забавный, безумно любит клавиатуру компютера, ноута и вообще любые кнопки:)))

Когда придумывали котенку имя, сразу решили, что оно будет связано с IT и программированием. Были такие варианты, как Бейсик и Паскаль:)))
Но остановились на Байте, по мотивам некогда опубликованном здесь рассказе "История одного байта" :)))
Вот и мы решили, что именно этого Байта нам и не хватало!
Байт у нас тоже программист, в совершенстве владеет Кис++
0

Я в Softpedia!


Долго я в нашем блоге не писал, чему были объективные причины (загруженность на работе и отсутствие инета дома). Но недавно мне на мыло пришло письмецо, от которого я просто обалдел и не могу об этом не написать.
Начну с того, что года 2 назад я захотел создать программку для автоматического запуска тестов для Java. То есть даешь ей директорию, она эту директорию прочесывает (а так же все вложенные) на предмет нахождения там классов, которые можно запустить на выполнение (т.е. классов, содержащих метод public static void main(String []).) Идея вроде простая и реализовать ее удалось, хотя сделать это оказалось гораздо сложнее, чем казалось:). Рабочий, но несколько глюкавый вариант моего творения под названием ClassTester лежит на Sourceforge тут. Так вот, письмецо, что мне пришло - о том, что сие творение "included in the Softpedia software database"!!! Что ж, я рад, обалденно рад, несмотря на то что за 2 с лишним года его скачали чуть больше 70 раз :). Письмо полно всяческих диферамбов в мой адрес, и даже если они просто пиарят таким образом свою Softpedi-ю, мне все равно приятно :)))))))))) А посему приведу текст письма полностью:

Congratulations,

ClassTester, one of your products, has been added to Softpedia's database
of software programs for the Windows operating system. It is featured with
a description text, screenshots, download links and technical details on
this page:
http://www.softpedia.com/get/Programming/Other-Programming-Files/ClassTester.shtml

The description text was created by our editors, using sources such as text
from your product's homepage, information from its help system, the PAD
file (if available) and the editor's own opinions on the program itself.


"ClassTester" has been tested in the Softpedia labs using several
industry-leading security solutions and found to be completely clean of
adware/spyware components. We are impressed with the quality of your
product and encourage you to keep these high standards in the future.

To assure our visitors that ClassTester is clean, we have granted it with
the "100% FREE" Softpedia award. To let your users know about this
certification, you may display this award on your website, on software
boxes or inside your product.

More information about your product's certification and the award is
available on this page:
http://www.softpedia.com/progClean/ClassTester-Clean-147780.html

Feel free to link to us using the URLs above. If you choose to link to the
clean award page for your product, you may use the award graphic or a text
link: "100% FREE award granted by Softpedia".

Your developer page on Softpedia can be reached at the URL below. It
contains the list of software products and a link to your website.
http://www.softpedia.com/developer/Lotrex-63739.html

А вот ссылочка для скачивания :)
0

Дружественные классы в Java

Что такое "дружественные классы"? В C++, насколько я знаю, если класс Class1 объявляет своим другом Class2, то Class2 может обращаться ко всем (в том числе и private-) полям и методам Class1:
class Class1
{
  friend: Class2;
private:
  int a, b;
};

class Class2
{
  public:
  changer(Classs1 *data int _a, int _b);
};

void Class2::changer(Classs1 *data int _a, int _b)
{
    data->a = _a;
    data->b = _b;
}

* This source code was highlighted with Source Code Highlighter.

Дружественые классы в Java - возможно ли это? И нужно ли вообще? На первый взгляд - казалось бы, не нужно. Ведь в Java отсутствует перегрузка операторов (а как правило, дружественные функции в программах на C++ - это функции-операторы). Но порой нужно, чтобы между классами были "особые отношения": например, Class1 содержит некие поля
данных, но "не знает", как эти поля корректно загружать из файла какого-то формата или получать от пользователя. Зато ClassA знает, как загружать/сохранять данные в формате A, ClassB знает как загружать/сохранять данные в формате B, а ClassUser умеет эти данные получать от пользователя/передавать пользователю. На первый взгляд, можно сделать Class1 абстрактным классом, содержащим абстрактные методы для загрузки/сохранения полей данных, и в классах ClassA и ClassB реализовать эти методы. Теперь мы сможем загружать и сохранять данные обоих форматов. А если необходимо загрузить данные из формата A и сохранить их в формате B? И при этом некоторые из полей данных класса Class1 только для чтения?
Сформулируем задачу следующим образом. Классы данных и форматов не связаны родственными узами, поскольку они все же решают разные задачи: Class1 позволяет хранить данные и как-то ими манипулировать, а классы ClassA и ClassB позволяют сохранять/загружать данные различных форматов. Но при этом классы ClassA и ClassB должны иметь доступ на запись к тем полям Class1, которые остальные классы могут только читать. И такие отношения в парах классов Class1 - ClassA и Class1 - ClassB можно назвать если не дружественными, то , по крайней мере, приятельскими :)
Мое решение проблемы:
0

Всем компьютерщикам и автомобилистам посвящается...


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

Началась эта истории, как и все подобные, с того, что изобрели компьютер. А уж когда компьютер настолько вошел в нашу жизнь, что любым утюгом или чайником мож­но управлять дистанционно посредством клика мышкой, то надежды на благополучный исход человечества из эпохи высоких технологий и вхождение в эпоху светлого будущего так помельчали, что никакие нано-технологии не помогут их хотя бы разглядеть.
Компьютеры везде! Медленно, но верно машины оккупировали планету Земля. А нам только кажется, что полиэстероловые друзья на службе у человечества: помогают ве­сти расчеты, контролировать, автоматизировать… На первый, неискушенный, взгляд, так оно и есть: банкоматы, электронные кассы, сотовые телефоны, бортовые компьютеры…
Бортовые компьютеры! Гениальное изобретение! Крути себе баранку, на педальки жми, а все остальное оставь технике.
3

Специально для жен программистов!!!

Отыскала на просторах Интернета.
3

One byte history

Этот рассказик у меня лежит на винте давным-давно. Когда-то наткнулся на него в сети, счас даже не вспомню, откуда его взял. Называется "История одного байта". Вспомнил я о нем наверно потому, что в настоящее время сам пишу программу для микроконтроллера, несмотря на то, что сталкиваюсь с совсем иными проблемами, нежели герой данного повествования. Скажу, зачем я его тут выкладываю... Дело в том, что все люди хотят, что бы их понимали, и я - не исключение. Что означает это слово - "понимание"? Имхо, это способность одного человека достаточно точно представлять, что переживает и как воспринимает нечто (события, действия, обстоятельства и т.п.) другой человек. Что переживает и чувствует человек, создающий программу? Наверно, что-то все же чувствует и что-то переживает, он ведь все же человек :) Написано куча кних о представителях творческих профессий - художниках, музыкантах, актерах... Очень хорошая есть книга о Ван-Гоге, называется "Жажда жизни" (правда она немного тяжеловата, но книга о жизни Ван-Гога вряд ли будет легкой). Этот рассказик - первое (и единственное, что я видел) сочинение подобного рода о программисте. По этой причине я бы очень хотел, чтобы его прочитали непрограммисты :) Не стоит пугаться непонятной терминологии, которая будет встречаться в тексте - имхо, для восприятия его сути знания этой терминологии не нужно.

(c) Dmitry Galuscenko

История одного байта
====================

Мне не хватало байта. Всего одного. Да, да. Того самого, что из восьми бит состоит. Что? Hет, я не псих, хотя одному богу известно, сколь тонкой была граница отделявшая меня от этого состояния. Hо все по порядку.
12

Микроконтроллеры и язык Си: указатели на функции

Последние пару месяцев я занимаюсь тем, что пишу программку для одного микроконтроллера (для M30624, семейство m16c/62). Хотя называть его "микроконтроллер" - не совсем правильно, поскольку микросхема эта довольно навороченная.

Частенько я программу для контроллера описываю в виде графа состояний. Имеется одна глобальная переменная STATE, в зависимости от значения которой вызываются соответствующие подпрограммы, например вот так:

while(1)
{
int res;
int cmd = getCommand();
switch(STATE)
{
case STATE_1:
res = sub_prog1(cmd);
break;
case STATE_2:
res = sub_prog2(cmd);
break;
...
..
case STATE_N:
res = sub_progN(cmd);
}
STATE = res;
}

В этот раз состояний оказалось многовато, более 20 штук (а точнее - 22). Возможно, я что-то не то сделал, и все это можно было как-то иначе описать, но... пока не хочется, думаю что и так все будет фурыкать. Другое дело, что неохота было такой громадный оператор switch расписывать. Тут я вовремя вспомнил про указатели на функции. Хорошая штука, только на работе, млин, ни одной книжки по Сям не оказалось, а я, как на зло, забыл, как оно называется. Искал в инете по словам "процедурный тип", "функциональный тип" и т.п, и ессно, ничего нужного мне не нашел. На скорую руку написал по памяти:

typedef int (*StateHandler)(int);

По моим представлениям, такое объявление дает понять компилятору, что StateHandler - это указатель на функцию, возвращающую тип int и принимающую один параметр тоже типа int. Как потом оказалось, правильно я его все-таки объявил :) После этого приведенный в начале поста код можно переписать уже вот так:

StateHandler handlers[] = {sub_prog1, sub_prog2, ... sub_progN};

while(1)
{
cmd = getCommand();
STATE = (*(handlers[STATE]))(cmd);
}

По-моему, получается короче, да и работать наверняка будет побыстрее. Главное, чтобы значения переменной STATE шли по-порядку, но имхо, это как раз не проблема.

2

Беззнаковые целые и Java

Недавно напоролся на один подводный камень в Java, который я до поры до времени обходил стороной потому, что не было необходимости собирать из байтов более длинные целые числа, а следовательно - и необходимости использовать поразрядные операции (сдвиг и т.п). Задача была простая - через порт от внешнего устр-ва приходит последовательность байт. Байты - это данные от 10-разрядного АЦП, первый байт - младший, второй - старший, третий - младший, четвертый - старший и т.д. Сделал я все как обычно, то есть наподобие того, как в этом примере:
import java.lang.*;

public class sign
{
public static void main(String [] args)
{
byte bytes[] = new byte[2];

bytes[0] = 0x56;//младший байт
bytes[1] = 0x02;//старший байт
short a = 0;
a = bytes[0];
a |= ((short)bytes[1]) << 8;
System.out.println("Value 1 = " + String.format("0x%04X", a) + "\r\n");
bytes[0] = (byte)0x85;//без оператора приведения не компилится
bytes[1] = 0x01;
a = bytes[0];
a |= ((short)bytes[1]) << 8;
System.out.println("Value 2 = " + String.format("0x%04X", a) + "\r\n");
}
}

Первый println выводит то, что и ожидалось - 0x256. Но вот второй... Сразу честно скажу: компилятор отказывался глотать этот пример, говоря, мол "possible loss of precision". Но в реальной ситуации байты шли из последовательного порта и предугадать их значения он в принципе не мог. И получалось у меня нечто невразумительное - примерно то, что выдавалось при печати во втором случае - вместо ожидаемого 0x0185 получилось 0xFF85. До сегодняшнего дня я думал, что беззнаковые числа нафиг не нужны и от них больше вреда, чем пользы, и авторы Java правильно сделали, что от них отказались. Но вот млин, были бы в они в Java. А еще лучше - наличие объединений (как в сях) или записей с вариантами (как в Паскале). Тогда бы вообще никаких сдвигов не надо, писваиваешь значения нужным полям, и... вуаля! Ну а по причине отсутствия в Java таких вкусностей, как объединения, проблему я решил следующим образом:
class sign2
{
public static void main(String [] args)
{
byte bytes[] = new byte[2];
short a;
bytes[0] = (byte)0x85;//без оператора приведения не компилится
bytes[1] = 0x01;
a = (short)(bytes[0] & 0x00FF);
a |= ((short)bytes[1]) << 8;
System.out.println("Value 2 = " + String.format("0x%04X", a) + "\r\n");
}
}

Конечно, аналог объединения можно сымитировать и в Java, но писанины много, да и доступ будет не на прямую, а через методы. Например, так:
class ByteShort
{
private short a = 0;
public void setFull(short d){ a = d; }
public short getFull(){return a; }
public void setByte(byte d, int index)
{
short mask = 0x00FF,
tmp = (short)(d & mask);
mask <<= index*8;
mask = (short)(~mask);
a &= mask;
a |= tmp;
}
public byte getByte(int index)
{
short tmp = (short)(a >> index*8);
return (byte)tmp;
}
}
Какой вывод можно сделать из всего этого? Я для себя вывод сделал следующий - из тех языков программирования, с которыми я знаком (Си, Си++, Java, Ada, Pascal, Fortran) пока нет такого, который был бы одинаково удобен как для быстрого создания приложений со сложной логикой, так и для написания программ взаимодействия с аппаратурой, и при этом безопасного. До этого случая на роль такого универсального языка (с моей точки зрения) претендовала Java, но счас... я прям в недоумении развожу руками.
8

Когда программиста отрывают от компа...



0

И снова повод есть у программистов...

Сегодня еще одна из версий дня программиста. Во всяком случае, есть повод отметить. 10-го декабря 1815-го года у поэта Джорджа Байрона и его супруги - Анны Изабеллы, которую муж за довольно сильное пристрастие к математике, ласково назвал «королева параллелограммов» появилась дочка.

Дочь сердца моего, малютка Ада!

Похожа ль ты на мать?

В последний раз, когда была мне суждена отрада,

Улыбку видеть детских синих глаз,

Я отплывал…


Байрон последний раз посмотрел на дочку, когда ей не исполнилось еще и месяца и… укатил в романтическое путешествие по Италии. «Королева параллелограммов», окончательно уставшая от мужниных причуд, сбежала к родителям и оба они представить себе не могли, что малышка Ада станет легендой кибернетики. Впрочем, мама как раз стремилась сделать все, чтобы насолить бывшему мужу, а насолить ему можно было только с математической точностью. В тринадцать лет малышка Ада уже рисовала модели летательных аппаратов, в восемнадцать встретила мужчину своей судьбы – мистера Бэббиджа. Он занимал кафедру профессора математики Кэмбриджского университета. То самое место, на котором полтора века назад работал сэр Исаак Ньютон. Вместе они придумали первый в мире компьютер и программы к нему. Деревянный «дисковод», картонные перфокарты, «процессор» на шестеренках и рычагах.

Текст самым наглым образом стащила отсюда

2

Книжечки для жены программиста


Купила я сегодня себе книжечку, да не простую, а как всегда для работы. Точнее для того чтобы повышать свою квалификацию верстальщика:) А книжечка называется "Скрипты в InDesign. Руководство для умных дизайнеров и ленивых верстальщиков", автор - Михаил Борисов. Не буду льстить себе и называть себя умным дизайнером,
а вот в том, что я ленивый верстальщик, признаюсь, положа руку на сердце:) Но самое интересное в том, что книжечка хоть и про InDesign, но большей частью про программирование, про написание скриптов для Indesign.
Много лет работала в этой программе и не знала к своему стыду ни про какие скрипты, все делала ручками. А вот угораздило меня выйти замуж за программиста и
книги мне теперь все странные какие-то попадаются: по моей тематике, но с уклоном в программирование. Может, программирование - это заразно?
Просто когда я изучала HTML и CSS, я об этом не задумывалась. Но теперь когда выбираю язык для изучения(выбираю между JavaScript и Visual Basic), на котором планирую ПИСАТЬ (страшно представить)эти
самые скрипты, прихожу к выводу, что программирование - это не сумасшествие, т.к. с ума сходят поодиночке, программирование - это какое-то эпидемиологическое заболевание, вакцины от которого нет, а иммунитет на него выработался далеко не у всех...