Vitalii Tsybulnyk / Виталий Цыбульник

On Software Development / О софтверной разработке

About the author

    Vitalii Tsybulnyk
Vitalii Tsybulnyk is a Software Engineering Manager at Mictosoft Azure.
E-mail me Send mail


Recent comments


The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008-2019

Матрица компетентности программистов

Computer Science   2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments data structures Doesn't know the difference between Array and LinkedList Able to explain and use Arrays, LinkedLists, Dictionaries etc in practical programming tasks Knows space and time tradeoffs of the basic data structures, Arrays vs LinkedLists, Able to explain how hashtables can be implemented and can handle collisions, Priority queues and ways to implement them etc. Knowledge of advanced data structures like B-trees, binomial and fibonacci heaps, AVL/Red Black trees, Splay Trees, Skip Lists, tries etc.   algorithms Unable to find the average of numbers in an array (It's hard to believe but I've interviewed such candidates) Basic sorting, searching and data structure traversal and retrieval algorithms Tree, Graph, simple greedy and divide and conquer algorithms, is able to understand the relevance of the levels of this matrix. Able to recognize and code dynamic programming solutions, good knowledge of graph algorithms, good knowledge of numerical computation algorithms, able to identify NP problems etc. Working with someone who has a good topcoder ranking would be an unbelievable piece of luck! systems programming Doesn't know what a compiler, linker or interpreter is Basic understanding of compilers, linker and interpreters. Understands what assembly code is and how things work at the hardware level. Some knowledge of virtual memory and paging. Understands kernel mode vs. user mode, multi-threading, synchronization primitives and how they're implemented, able to read assembly code. Understands how networks work, understanding of network protocols and socket level programming. Understands the entire programming stack, hardware (CPU + Memory + Cache + Interrupts + microcode), binary code, assembly, static and dynamic linking, compilation, interpretation, JIT compilation, garbage collection, heap, stack, memory addressing...   Software Engineering   2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments source code version control Folder backups by date VSS and beginning CVS/SVN user Proficient in using CVS and SVN features. Knows how to branch and merge, use patches setup repository properties etc. Knowledge of distributed VCS systems. Has tried out Bzr/Mercurial/Darcs/Git   build automation Only knows how to build from IDE Knows how to build the system from the command line Can setup a script to build the basic system Can setup a script to build the system and also documentation, installers, generate release notes and tag the code in source control   automated testing Thinks that all testing is the job of the tester Has written automated unit tests and comes up with good unit test cases for the code that is being written Has written code in TDD manner Understands and is able to setup automated functional, load/performance and UI tests   Programming   2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments problem decomposition Only straight line code with copy paste for reuse Able to break up problem into multiple functions Able to come up with reusable functions/objects that solve the overall problem Use of appropriate data structures and algorithms and comes up with generic/object-oriented code that encapsulate aspects of the problem that are subject to change.   systems decomposition Not able to think above the level of a single file/class Able to break up problem space and design solution as long as it is within the same platform/technology Able to design systems that span multiple technologies/platforms. Able to visualize and design complex systems with multiple product lines and integrations with external systems. Also should be able to design operations support systems like monitoring, reporting, fail overs etc.   communication Cannot express thoughts/ideas to peers. Poor spelling and grammar. Peers can understand what is being said. Good spelling and grammar. Is able to effectively communicate with peers Able to understand and communicate thoughts/design/ideas/specs in a unambiguous manner and adjusts communication as per the context This is an often under rated but very critical criteria for judging a programmer. With the increase in outsourcing of programming tasks to places where English is not the native tongue this issue has become more prominent. I know of several projects that failed because the programmers could not understand what the intent of the communication was. code organization within a file no evidence of organization within a file Methods are grouped logically or by accessibility Code is grouped into regions and well commented with references to other source files File has license header, summary, well commented, consistent white space usage. The file should look beautiful.     2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments code organization across files No thought given to organizing code across files Related files are grouped into a folder Each physical file has a unique purpose, for e.g. one class definition, one feature implementation etc. Code organization at a physical level closely matches design and looking at file names and folder distribution provides insights into design   source tree organization Everything in one folder Basic separation of code into logical folders. No circular dependencies, binaries, libs, docs, builds, third-party code all organized into appropriate folders Physical layout of source tree matches logical hierarchy and organization. The directory names and organization provide insights into the design of the system. The difference between this and the previous item is in the scale of organization, source tree organization relates to the entire set of artifacts that define the system. code readability Mono-syllable names Good names for files, variables classes, methods etc. No long functions, comments explaining unusual code, bug fixes, code assumptions Code assumptions are verified using asserts, code flows naturally - no deep nesting of conditionals or methods   defensive coding Doesn't understand the concept Checks all arguments and asserts critical assumptions in code Makes sure to check return values and check for exceptions around code that can fail. Has his own library to help with defensive coding, writes unit tests that simulate faults     2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments error handling Only codes the happy case Basic error handling around code that can throw exceptions/generate errors Ensures that error/exceptions leave program in good state, resources, connections and memory is all cleaned up properly Codes to detect possible exception before, maintain consistent exception handling strategy in all layers of code, come up with guidelines on exception handling for entire system.   IDE Mostly uses IDE for text editing Knows their way around the interface, able to effectively use the IDE using menus. Knows keyboard shortcuts for most used operations. Has written custom macros   API Needs to look up the documentation frequently Has the most frequently used APIs in memory Vast and In-depth knowledge of the API Has written libraries that sit on top of the API to simplify frequently used tasks and to fill in gaps in the API E.g. of API can be Java library, .net framework or the custom API for the application frameworks Has not used any framework outside of the core platform Has heard about but not used the popular frameworks available for the platform. Has used more than one framework in a professional capacity and is well-versed with the idioms of the frameworks. Author of framework     2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments requirements Takes the given requirements and codes to spec Come up with questions regarding missed cases in the spec Understand complete picture and come up with entire areas that need to be speced Able to suggest better alternatives and flows to given requirements based on experience   scripting No knowledge of scripting tools Batch files/shell scripts Perl/Python/Ruby/VBScript/Powershell Has written and published reusable code   database Thinks that Excel is a database Knows basic database concepts, normalization, ACID, transactions and can write simple selects Able to design good and normalized database schemas keeping in mind the queries that'll have to be run, proficient in use of views, stored procedures, triggers and user defined types. Knows difference between clustered and non-clustered indexes. Proficient in use of ORM tools. Can do basic database administration, performance optimization, index optimization, write advanced select queries, able to replace cursor usage with relational sql, understands how data is stored internally, understands how indexes are stored internally, understands how databases can be mirrored, replicated etc. Understands how the two phase commit works.   Experience   2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments languages with professional experience Imperative or Object Oriented Imperative, Object-Oriented and declarative (SQL), added bonus if they understand static vs dynamic typing, weak vs strong typing and static inferred types Functional, added bonus if they understand lazy evaluation, currying, continuations Concurrent (Erlang, Oz) and Logic (Prolog)   platforms with professional experience 1 2-3 4-5 6+   years of professional experience 1 2-5 6-9 10+   domain knowledge No knowledge of the domain Has worked on at least one product in the domain. Has worked on multiple products in the same domain. Domain expert. Has designed and implemented several products/solutions in the domain. Well versed with standard terms, protocols used in the domain.   Knowledge   2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments tool knowledge Limited to primary IDE (VS.Net, Eclipse etc.) Knows about some alternatives to popular and standard tools. Good knowledge of editors, debuggers, IDEs, open source alternatives etc. etc. For e.g. someone who knows most of the tools from Scott Hanselman's power tools list. Has used ORM tools. Has actually written tools and scripts, added bonus if they've been published.   languages exposed to Imperative or Object Oriented Imperative, Object-Oriented and declarative (SQL), added bonus if they understand static vs dynamic typing, weak vs strong typing and static inferred types Functional, added bonus if they understand lazy evaluation, currying, continuations Concurrent (Erlang, Oz) and Logic (Prolog)   codebase knowledge Has never looked at the codebase Basic knowledge of the code layout and how to build the system Good working knowledge of code base, has implemented several bug fixes and maybe some small features. Has implemented multiple big features in the codebase and can easily visualize the changes required for most features or bug fixes.   knowledge of upcoming technologies Has not heard of the upcoming technologies Has heard of upcoming technologies in the field Has downloaded the alpha preview/CTP/beta and read some articles/manuals Has played with the previews and has actually built something with it and as a bonus shared that with everyone else     2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments platform internals Zero knowledge of platform internals Has basic knowledge of how the platform works internally Deep knowledge of platform internals and can visualize how the platform takes the program and converts it into executable code. Has written tools to enhance or provide information on platform internals. For e.g. disassemblers, decompilers, debuggers etc.   books Unleashed series, 21 days series, 24 hour series, dummies series... Code Complete, Don't Make me Think, Mastering Regular Expressions Design Patterns, Peopleware, Programming Pearls, Algorithm Design Manual, Pragmatic Programmer, Mythical Man month Structure and Interpretation of Computer Programs, Concepts Techniques, Models of Computer Programming, Art of Computer Programming, Database systems , by C. J Date, Thinking Forth, Little Schemer   blogs Has heard of them but never got the time. Reads tech/programming/software engineering blogs and listens to podcasts regularly. Maintains a link blog with some collection of useful articles and tools that he/she has collected Maintains a blog in which personal insights and thoughts on programming are shared   Источник

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Wednesday, October 10, 2012 5:50 AM
Permalink | Comments (1) | Post RSSRSS comment feed

В помощь студентам и ВУЗам: Windows Azure Educator Grants

Цитирую аннонс программы: Faculty have long been requesting a way to teach with the Windows Azure platform. Meanwhile, technical students have been flocking to our Windows Azure events to get their first exposure and incorporating Windows Azure platform into their Imagine Cup solutions at record numbers. To secure the next generation on our platform, I am happy to announce the broad availability of the Windows Azure Educator Grants. Through the Windows Azure Educator Grants, faculty can request 5 month Windows Azure Passes, which do NOT require any Credit Card, for themselves and their students. Faculty can apply for these grants through the Educators Page on  For details on the resources provided please visit the Windows Azure Educator’s page. If faculties have requirements which are not met by the resources above they can contact us at and we may be able to provide necessary adjustments. This includes the ability for faculty to request time extensions on their specific accounts, prior to account expiration, for another 5 months so they will not need to transfer their accounts which include curriculum specific materials from one semester to another.  For any influential faculty help please email the Windows Azure Education team at

Posted by Vitalii Tsybulnyk on Friday, May 4, 2012 6:13 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Inside Windows Azure

Cloud Computing and Windows Azure were the leading subjects of PDC 2010 last fall. Fortunately, there are a lot of amazing videos of the presentations available, and Inside Windows Azure by Mark Russinovich is definitely my favorite. Mark provides a very clear 'big picture' review of Windows Azure's features and internal arrangement. He gives just the right amount of technical details to be useful to a wide audience, from cloud application developers to software product owners and company leaders. I highly recommend this video to anybody who is interested in modern IT trends in general and cloud computing in particular.

Posted by Vitalii Tsybulnyk on Friday, January 14, 2011 4:06 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Как я победил спам в комментариях к своему блогу

Всё началось несколько месяцев назад, когда в комментарях к постам моего блога начал появляться спам. Сначала я даже не понял, что это спам, так как сообщения носили в большинстве своём довольно невинный характер, например "What a wonderful post!" или "I agree 100%". Единственное, что их отличало от "нормальных" комментариев - это завидная регулярность (несколько комментариев в неделю, что для моего блога выше среднего) и ссылка на какой-нибудь коммерческий сайт в поле "Website". Кроме того, спам был исключительно на английском языке, что опять же нехарактерно для моего на 90% русскоязычного блога. Когда текст спамерских комментариев стал повторяться, я заподозрил неладное и предпринял Шаг 1. Модерация комментариев. Сама по себе модерация комментариев не избавляет от спама, скорее наоборот, заставляет уделять время модерированию даже человеческих комментариев, однако модерация позволила избавить от спама хотябы читателей моего блога, которые получали спам в виде ответов на их собственные комментарии. Модерация не утруждала меня до тех пор, пока количество спама не выросло от нескольких сообщений в неделю до нескольких сообщений в день. Тогда я уделил время выяснению вопроса о том, как же предлагают бороться с этой проблемой создатели BlogEngine.NET, который я использую в качестве движка для своего блога. Оказалось,  в нём реализован механизм под названием CAPTCHA, который заключается в наличии скрытого поля, в которое роботы-спамеры будут заносить некое значение, а человек - нет, что и помогает отличить робота от человека. Вполне логично для меня, роботы просто не заносят ничего в скрытые поля, тем самым нейтрализуя эту защиту. Чтобы как-то затруднить роботам жизнь, я предпринял Шаг 2. Вместо скрытого поля CAPTCHA, я сделал его открытым, но поместил в скрытый DIV. Это не избавило от спама полностью, видимо некоторые роботы оказались достаточно умными, чтобы пройтись вверх по иерархии DOM-элементов и проверить их состояние. Однако количество таких "умников" снова упало до вполне приемлемого для модерации числа, так что я получил перерыв ещё в несколько месяцев. Однако по прошествии некоторого времени количество спамерских сообщений снова стало быстро расти, что заставило меня вернуться к изучению этого вопроса. Оказалось, появилось уже довольно много жалоб на нееффективность метода CAPTCHA, так что авторы движка BlogEngine.NET разработали новое решение в виде Шаг 3. Автоматическое модерирование комметариев. Автоматическое модерирование включает в себя несколько довольно очевидных правил, а для борьбы со спамом прелагается парочка фильтров (StopForumSpam, AkismetFilter), суть работы которых заключается в проверке комментария на "добропорядочность" через некие онлайн-сервисы, которые по задумке авторов собирают все спамерские сообщения в свои базы и таким образом умеют отличать их от человеческих. Соответственно, если комментарий ошибочно причислен к разряду человеческих, имеется возможность уведомлять об этом сервис, тем самым улучшая его. После нескольких дней использования доступных для BlogEngine.NET фильтров, стало очевидным, что их эффективность не многим превышает 50%. Т.е. около половины спама благополучно оседало на страницах моего блога, что естественно меня не устраивало и заставило вернуться назад к ручному модерированию. Исчерпав таким образом стандартные возможности по защите от спама, предоставляемые движком, я начал задумываться о собственном решении. Первое и самое незатратное по времени решение, которое пришло мне в голову - это Шаг 4. Добавить обязательное поле и валидатор к нему, не пропускающий ничего, кроме определённого сообщения. В качестве "секретного" сообщения я выбрал "I'm human", а чтобы читатели знали, что вводить в это поле, рядом с полем значилось "Защита от спама, введите "I'm human"". Реализация этого решения заняла всего несколько минут моего времени и сократила поток спама в несколько раз, тем самым снова вернув его количество в рамки приемлемого для ручной модерации. Однако снова ненадолго. У меня есть несколько версий того, как роботы-спамеры обходили мою защиту, но суть остается той же - объём спама довольно быстро вернулся на прежний уровень, а потом и превзошёл его. На пике спамерской активности я получал до 1000 спамерских сообщений в день, что вышло за рамки всего разумного и вынудило меня просто не читая удалять все комментарии на английском языке. Анализ IP оставивших спамерские комментарии пользователей показал, что большинство спамерских атак происходило из Китая. Таким образом, мне не осталось ничего, как выделить время на полноценное решение, коим стал Шаг 5. Картинка с текстом. На форму для комментария я поместил генерируемую в коде картинку с несколько искажённым текстом и поле для ввода этого текста пользователем. При отправке комментария мой код на сервере сверяет эти два текста и либо принимает комментарий, либо отвергает как спамерский. Реализация этого решения несколько затруднилась тем, что отправка комментариев в BlogEngine.NET осуществляется через ASP.NET AJAX, причём конкретный способ использования этого инструмента (на мой взгляд) оставляет желать лучшего. Кроме того, мне не хотелось вносить слишком много изменений в незнакомый мне код, так что для некоторых моментов я предпочёл простоту 100%-ной элегантности. Тем не менее, после нескольких часов реализации и отладки всё заработало как надо. С момента внесения этих изменений я не получил ни одного спамерского сообщения, что вселяет в меня оптимизм по поводу его долгосрочности (или же вызывает опасения о работоспособности формы для комментария ). Если кого-то заинтересовала реализация данного решения для BlogEngine.NET - пишите (в комментарии ), и я выложу детали внесённых мною правок.

Categories: Development
Posted by Vitalii Tsybulnyk on Tuesday, December 7, 2010 6:59 AM
Permalink | Comments (4) | Post RSSRSS comment feed

Design Guidelines for Developing Frameworks and Class Libraries

After I spent the last couple of months designing some class library for Windows Azure engineering infrastructure, I realized that design principles for frameworks and class libraries are not exactly the same as for 'off the shelf' or enterprise applications and systems. The fundamental difference is that, in the case of applications, customers don't care about your code at all, so you can use all techniques you want to make your design elegant and easy to maintain. In the case of framework/library, quite the contrary is true: your code is in some ways a user interface, which customers see, use, and care about a lot. Believe it or not, this difference significantly influences your architecture and OOD decisions in ways you may not expect. In this post, I've collected the advice I'd give to framework/library designers. Some of these suggestions are based on these sources [1-2]; however, most of them are from my own experience. Some of this advice might contradict traditional design principles, so be careful and use them for public API/frameworks only. Fundamentals 1. Framework designers often make the mistake of starting with the design of the object model (using various design methodologies) and then write code samples based on the resulting API. The problem is that most design methodologies (including most commonly used object-oriented design methodologies) are optimized for the maintainability of the resulting implementation, not for the usability of the resulting APIs. They are best suited for internal architecture designs—not for designs of the public API layer of a large framework. When designing a framework, you should start with producing a scenario-driven API specification. This specification can be either separate from the functional specification or can be a part of a larger specification document. In the latter case, the API specification should precede the functional one in location and time. The specification should contain a scenario section listing the top 5-10 scenarios for a given technology area and show code samples that implement these scenarios. 2. Common scenario APIs should not use many abstractions but rather should correspond to physical or well-known logical parts of the system. As noted before, standard OO design methodologies are aimed at producing designs that are optimized for maintainability of the code base. This makes sense as the maintenance cost is the largest chunk of the overall cost of developing a software product. One way of improving maintainability is through the use of abstractions. Because of that, modern design methodologies tend to produce a lot of them. The problem is that frameworks with lot of abstractions force users to become experts in the framework architecture before starting to implement even the simplest scenarios. But most developers don’t have the desire or business justification to become experts in all of the APIs such frameworks provide. For simple scenarios, developers demand that APIs be simple enough so that they can be used without having to understand how the entire feature areas fit together. This is something that the standard design methodologies are not optimized for, and never claimed to be optimized for. Naming Guidelines 3. The code samples should be in at least two programming languages. This is very important as sometimes code written using those languages differs significantly. It is also important that these scenarios be written using different coding styles common among users of the particular language (using language specific features). The samples should be written using language-specific casing. For example, VB.NET is case-insensitive, so samples should reflect that. Think about different languages even when you name classes, e.g. don't make mistakes like the NullReferenceException class which can be thrown by VB code, but VB uses Nothing, not null. Avoid using identifiers that conflict with keywords of widely used programming languages. 4. The simplest, but also most often missed opportunity for making frameworks self-documenting is to reserve simple and intuitive names for types that developers are expected to use (instantiate) in the most common scenarios. Framework designers often “burn” the best names for less commonly used types, with which most users do not have to be concerned. For example, a type used in mainline scenarios to submit print jobs to print queues should be named Printer, rather than PrintQueue. Even though technically the type represents a print queue and not the physical device (printer), from the scenario point of view, Printer is the ideal name as most people are interested in submitting print jobs and not in other operations related to the physical printer device (such as configuring the printer). If you need to provide another type that corresponds, for example, to the physical printer to be used in configuration scenarios, the type could be called PrinterConfiguration or PrinterManager. Similarly, names of most commonly used types should reflect usage scenarios, not inheritance hierarchy. Most users use the leaves of an inheritance hierarchy almost exclusively, and are rarely concerned with the structure of the hierarchy. Yet, API designers often see the inheritance hierarchy as the most important criterion for type name selection. For example, naming the abstract base class File and then providing a concrete type NtfsFile works well if the expectation is that all users will understand the inheritance hierarchy before they can start using the APIs. If the users do not understand the hierarchy, the first thing they will try to use, most often unsuccessfully, is the File type. While this design works well in the object-oriented design sense (after all NtfsFile is a kind of File) it fails the usability test, because “File” is the name most developers would intuitively think to program against. Classes vs. Interfaces 5. In general, classes are the preferred construct for exposing abstractions. The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs. Once you ship an interface, the set of its members is fixed forever. The only way to evolve interface-based APIs is to add a new interface with the additional members. A class offers much more flexibility. 6. Abstract types do version much better, then allow for future extensibility, but they also burn your one and only one base type. Interfaces are appropriate when you are really defining a contract between two objects that is invariant over time. Abstract base types are better for define a common base for a family of types. 7. When a class is derived from a base class, I say that the derived class has an IS-A relationship with the base. For example, a FileStream IS-A Stream. However, when a class implements an interface, I say that the implementing class has a CAN-DO relationship with the interface. For example, a FileStream CAN-DO disposing. Methods vs. Properties There are two general styles of API design in terms of usage of properties and methods: method-heavy APIs, where methods have a large number of parameters and the types have fewer properties, and property-heavy APIs, where methods with a small number of parameters and more properties to control the semantics of the methods. 8. All else being equal, the property-heavy design is generally preferable. 9. Properties should look and act like fields as much as possible because library users will think of them and use them as though they were fields. 10. Use a method, rather than a property, in the following situations:  - The operation is orders of magnitude slower than a field access would be. If you are even considering providing an asynchronous version of an operation to avoid blocking the thread, it is very likely that the operation is too expensive to be a property. In particular operations that access the network or the file system (other than once for initialization) should likely be methods, not properties.  - The operation returns a different result each time it is called, even if the parameters don’t change. For example, the Guid.NewGuid method returns a different value each time it is called.  - The operation has a significant and observable side effect. Notice that populating an internal cache is not generally considered an observable side effect.  - The operation returns an array. Properties that return arrays can be very misleading. Usually it is necessary to return a copy of an internal array so that the user cannot change the internal state. This may lead to inefficient code. Events 11. Consider using a subclass of EventArgs as the event argument, unless you are absolutely sure the event will never need to carry any data to the event handling method. If you ship an API using EventArgs directly, you will never be able to add any data to be carried with the event without breaking compatibility. If you use a subclass, even if initially completely empty, you will be able to add properties to the subclass when needed. Enums 12. Use enums if otherwise a member would have two or more Boolean parameters. Enums are much more readable when it comes to books, documentation, source code reviews, etc. Consider a method call that looks as follows. FileStream f = File.Open (“foo.txt”, true, false); This call gives the reader no context with which to understand the meaning behind true and false. The call would be much more usable if it were to use enums, as follows: FileStream f = File.Open(“foo.txt”, CasingOptions.CaseSensitive, FileMode.Open); Some would ask why we don’t have a similar guideline for integers, doubles, etc. Should we find a way to “name” them as well? There is a big difference between numeric types and Booleans. You almost always use constants and variables to pass numeric values around, because it is good programming practice and you don’t want to have “magic numbers”. However, if you take a look at real life source code, this is almost never true of Booleans. 80% of the time a Boolean argument is passed in as a literal constant, and its intention is to turn a piece of behavior on or off. We could alternatively try to establish a coding guideline that you should never pass a literal value to a method or constructor, but I don’t think it would be practical. I certainly don’t want to define a constant for each Boolean parameter I’m passing in. Methods with two Boolean parameters, like the one in the example above, allow developers to inadvertently switch the arguments, and the compiler and static analysis tools can't help you. Even with just one parameter, I tend to believe it's still somewhat easier to make a mistake with Booleans ... let's see, does true mean "case insensitive" or "case sensitive"?   Sources 1. MSDN 'Design Guidelines for Developing Class Libraries' 2. Krzysztof Cwalina, Brad Abrams 'Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries'

Posted by Vitalii Tsybulnyk on Thursday, August 26, 2010 2:07 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Немного об облаках

Несмотря на шумиху в прессе и в умах, которую пару последних лет производит Майкрософт по поводу своей (и не только своей) "облачной" (cloud) стратегии, очень многие опытные разработчики и руководители всё ещё не совсем представляют как эти изменения отражаются (отразятся) на их непосредственной профессиональной деятельности. Хорошим примером для меня стало то, что когда я сообщал своим коллегам в Майкрософт (а также экс-коллегам, друзьям и просто знакомым соратникам по цеху) о своём переходе в команду разработки Windows Azure, наиболее распространённой реакцией была "А что он делает этот Windows Azure?" Поэтому я и решился на написание этого поста - одним махом дать представление о прогрессе в облачном движении вообще и том вкладе, который в это движение делает Microsoft.   Для меня концепцию "облачного" движения проще всего раскрывать в сравнении с каким-либо другим технологическим скачком человечества, позвольте мне остановиться на примере изобретения и внедрения электричества.   Облака вчера.  Основные идеи cloud computing совершенно не новы. По сути, "облаком" можно назвать любой ресурс или приложение, используемое параллельно несколькими (многими) пользователями. Пожалуй даже самые первые суперкомпьютеры, с которыми большое число пользователей работало по принципу терминального доступа, уже можно относить к первым образцам "облака". Этот этап в создании и освоении "облачной" идеи можно сравнить с периодом 1650-1700 гг, когда Отто фон Герике экспериментировал со своей электрической машиной по извлечению искр из натираемого шара, которые и были по сути первыми экспериментами с электричеством. Однако технологии быстро развивались, и появление в конце 1980-х Интернета можно смело назвать зарождением "облачной" идеи в том виде, в котором мы её знаем сегодня: хост-провайдеры предоставляли платформу, на которой владельцы приложений могли разворачивать свои веб-приложения для использования их в качестве сервисов. Проводя параллели с освоением электричества, это период с 1700 по 1825 годы, когда такими учёными как Вольт, Фарадей и Ом были открыты, сформулированы и использованы все основные законы электростатики и электродинамики. Однако до массового использования этих знаний оставалось ещё пол века. Если бы мы в это время подошли к случайному прохожему и спросили "как вы относитесь к электричеству?", нас мы скорее всего встретил недоумённый взгляд.   Облака сегодня. Что же произошло два или три года назад такого, что послужило толчком всей этой "облачной лихорадке", которую мы наблюдаем сегодня? Попросту говоря, технологии и инфраструктура Интернета достигли уровня, достаточного для того, чтобы всерьёз говорить о предоставлении совершенно любых приложений в виде интернет-сервисов. Интернет стал такой же неотъемлемой частью нашего быта, как водопровод, телефон и то же самое электричество, которое достигло аналогичного этапа в своём развитии в 1870-х годах, когда были сконструированы первые электрогенераторы и начали строиться первые электростанции, а на улицах Парижа вспыхнули первые дуговые электролампы. Windows Azure - это по сути и есть электростанции, которые позволяют потребителям облака не заботится о построении облачной инфраструктуры, достаточно просто купить этот сервис у людей, делающих это профессионально. Покупая доступ к облаку Microsoft, Amazon, Google или любому другому, вы избавляете себя от необходимости крутить динамо-машину и трансформировать полученное электричество, вы просто подключаетесь к линии электропередач и платите за количество потреблённых кВатт-часов. Облака завтра. Собственно будущее облаков вобще и  Windows Azure в частности и натолкнуло меня на написание этого поста. Многих потребителей не устраивает зависимость от централизованой электрической сети - хочется и гарантий независимости, и 100% надёжности. Точно так, многих в облачной идее смущает именно вопрос безопасности конфиденциальных данных размещённых в публичном облаке, а также надёжности предоставляемого сервиса. Для 95% потребителей надёжность и безопасность data-центров того же Microsoft на две головы превосходит надёжность того, что они могут построить сами. Однако оставшиеся 5% (а в будещем это число может расти) хотят и могут платить за то, чтобы иметь надёжное облако и безопасное для себя и только для себя. Именно для этой категории пользователей  Microsoft анонсировал Windows Azure Platform appliance - платформу  Windows Azure, которую клиенты смогут разворачивать на своих собственных data-центрах. Таким образом для пользователей, инвестирующих в разработку своих сервисов под Windows Azure сейчас, гарантируется что они могут быть в будущем перенесены в приватные data-центры на базе Windows Azure Platform appliance:       We are delivering a game-changing cloud service with Windows Azure.  Windows Azure is the world’s first all-purpose cloud platform that allows customers to focus on creating business solutions without worrying about the underlying infrastructure.  At the same time, we are enabling customers to build their own cloud within their custom environments using our Windows Server, SQL Server, and System Center products. Building on these unique assets, at WPC, we took a big step forward with the announcement of the Windows Azure Platform appliance, a turnkey cloud platform that customers can deploy in their own datacenters, spanning from hundreds to thousands of servers. When we announced the launch of the first wave of the Windows Azure appliance, we effectively changed the cloud game in the industry.  Through this announcement, we’re making cloud computing more accessible than ever before by taking everything we've learned through running clouds ourselves (Hotmail, Bing, Microsoft Online Services, etc.), packaging it up, and delivering it to the industry.  With the help of companies like Dell, eBay, Fujitsu, HP and others, we believe this innovative step will change the face of cloud computing. With the announcement of the Windows Azure appliance, Microsoft has redefined cloud computing by being the only vendor that is delivering across all aspects of the cloud. Мне кажется, что это один-в-один повторяет тенденцию использования особо энерго-зависимыми учреждениями (и частными лицами) электрических мини-генераторов или портативных электростанций чтобы обезопасить себя от перебоев с поставками электроенергии и от стратегической зависимости от этих поставок, что в очередной раз подверждает теорию спиральности технического прогресса, когда все новые идеи и открытия всегда отражают некие старые, только уже в новом качестве.

Posted by Vitalii Tsybulnyk on Friday, July 16, 2010 10:33 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Успешная человеческая многозадачность в софтверной разработке

В июньском номере журнала "Управление проектами" вышла ещё одна статья "Успешная человеческая многозадачность в софтверной разработке", подводящая итог моим идеям по теме, которую я уже частично упоминал в своих ранних постах. Полный текст статьи будет доступен только через пол года, сейчас приходится ограничиваться аннотацией: Частое переключение между задачами принято рассматривать в науке управления проектами как исключительно негативный подход. Однако бизнес-модель софтверной разработки иногда требует прогресса в выполнении нескольких задач параллельно, чего можно достичь только частым переключением между ними. В статье автор делится собственным опытом и разработанными на его основании правилами, позволяющими эффективно работать над несколькими задачами одновременно. Соблюдение изложенных правил позволяет с большой вероятностью избежать падения продуктивности при многозадачной работе, а в некоторых случаях даже добиться некоторого роста суммарной продуктивности.

Posted by Vitalii Tsybulnyk on Sunday, June 27, 2010 6:29 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Planning Good QA Automation Scope

It seems to me that the most important part of a successful automated test infrastructure is an elegant approach for test planning/coverage/prioritizing. Below are my thoughts and ideas on how this approach should look for a high-quality long-term software project. In order for your automated tests to be reliable and fast enough, but also to test the product the same way customers actually use it, you should have different types of tests for different purposes. Here is a classification which looks reasonable to me: · Feature (API) tests – each test in this category should cover one particular small product feature. You should exclude all extra product activity (e.g. pre-requisites creation, product configuration) and replace it with test code. This test should run in the fastest and the most reliable way, so API should be used instead of UI when possible. Feature tests have to be 100% reliable and fast, so you should be able to run them nightly. · Scenario (UI) tests should cover several (not many) features each and test them the way the customer really uses them – via UI. To keep these tests comparatively short, some pre-requisites might be pre-created with test code; however all steps involved into customer scenario should be done with UI. Each scenario test will probably cover several features, so Coverage matrix should be tracked to make sure that the feature coverage is full and even, e.g.:   Scenario 1 Scenario 2 Scenario 3 Scenario 4 Feature 1 X X Feature 2 X X X Feature 3 X X Feature 4 X X X Feature 5 X X X Scenario tests take much longer to execute and are less reliable then feature tests (because they use UI, a problem in one feature could fail several scenarios, etc.), so they should be run rarely. · End-to-End (UI) tests cover many features (often the whole feature area), which makes this test the closest representation of actual user activity and provides the highest level of integration testing. E2E tests are super long and the least reliable among all test types, so they should be run very rarely. · Stress (API) tests are in fact feature tests, but run many times each. Test infrastructure should allow for running feature tests just in ‘stress’ mode, without writing separate stress tests. · Fuzz (API) tests are in fact feature tests, but run several times each with different prerequisites and various (random) input. Test infrastructure should allow for running feature tests just in ‘fuzz’ mode without writing separate fuzz tests. So you should plan and run tests according to the matrix of test types and test targets, e.g.:   Feature (API) Scenario (UI) E2E (UI) Stress (API) Fuzz (API) Module 1 nightly weekly monthly monthly monthly Module 2 nightly weekly bimonthly bimonthly bimonthly Module 3 weekly monthly bimonthly bimonthly bimonthly or   Feature (API) Scenario (UI) E2E (UI) Stress (API) Fuzz (API) OS 1 nightly weekly monthly monthly monthly OS 2 nightly weekly bimonthly bimonthly bimonthly OS3 weekly monthly bimonthly bimonthly bimonthly

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Friday, June 11, 2010 7:23 AM
Permalink | Comments (2) | Post RSSRSS comment feed

Visual Studio Isolated Shell: интегрированная среда разработчика своими руками

ВВЕДЕНИЕ  Думаю, излишне говорить о том, как важен удобный и профессионально выглядящий пользовательский интерфейс для успеха программного продукта. Однако качественный и богатый возможностями пользовательский интерфейс - весьма дорогостоящее удовольствие. Он требует не только существенных дополнительных затрат на разработку дизайна, анализ удобства использования, но и влечёт за собой растущие в геометрической прогрессии затраты на тестирование и отладку. Один из таких классов дорогостоящих интерфейсов - это MDI (multiple document interface - многодокументный интерфейс). Разработка программного продукта с редактором файлов, удобной манипуляцией окнами, toolbox и toolwindow - это на 80% разработка интерфейса, и только на 20% разработка собственно уникальной для вашего продукта бизнес-логики. Использование таких библиотек, как MFC для С++ или Infragistics для .Net, бесспорно, очень помогает, но не спасает в такой ситуации. В данной статье я хотел бы рассказать об ещё одном, сравнительно новом подходе к созданию профессионального многодокументного пользовательского интерфейса от Microsoft под названием Visual Studio Isolated Shell. ОСНОВНЫЕ ПРИНЦИПЫ Visual Studio Isolated Shell представляет собой облегчённую версию оболочки Visual Studio, которую разработчик может использовать для создания собственного продукта. Т.е. в распоряжение разработчиков предлагается вся мощь Visual Studio IDE, включая меню, редактор файлов, toolbox и toolwindow, которую они могут наполнят своей собственной бизнес-логикой и получать таким образом профессиональное приложение с богатыми возможностями графического интерфейса, не уступающими лидерам рынка. У такого использования есть и своя цена - для реализации уникальной бизнес-логики внутри оболочки разработчику предоставляется ограниченный набор инструментов, предназначенный для расширения возможностей стандартной оболочки Visual Studio. Таким образом, архитектура построенного на базе Isolated Shell приложения представляет собой конгломерат из собственно самой оболочки и расширений к ней, реализующих уникальную бизнес-логику приложения.  СОЗДАНИЕ ПРОЕКТА  Isolated Shell впервые появилась в Visual Studio 2008, однако в этой статье я буду ссылаться на Visual Studio 2010 RC, так как в этой новой версии есть ряд усовершенствований и дополнительных возможностей. Для создания собственного проекта Isolated Shell вам понадобится Visual Studio 2010 RC Ultimate/Professional и Visual Studio 2010 SDK RC. После установки VS SDK в списке доступных проектов ('File' -> 'New' -> 'Project') появится 'Other Project Type' -> 'Extensibility' -> 'Visual Studio Shell Isolated'. Создайте этот проект - в окне сразу откроется описание "Starter Kit", которое можно использовать в качестве первого руководства в мир Isolated Shell. Если при создании проекта вы оставили название по умолчанию 'VSShellStub1', то ваше решение состоит из четырёх проектов: VSShellStub1 - ядро оболочки (С++) VSShellStub1UI - проект-спутник (satellite dll) оболочки, содержащий некоторые ресурсы (С++) VSShellStub1.AboutBoxPackage - пример расширяющего вашу оболочку интерграционного пакета (Integration Package), реализующий простой диалог "About Box' (C#) ShellExtensionsVSIX - проект расширения для оболочки, по умолчанию содержащий только интерграционный пакет VSShellStub1.AboutBoxPackage (C#) Cкомпилируйте и запустите решение. Мои поздравления - вы увидете оболочку вашего будущего проекта, весьма напоминающую Visual Studio, но лишённую характерных иконок и прочих логотипов. Пункт меню 'Help' содержит ссылку на диалог "About Box', содержащийся в созданном по умолчанию расширении. РАСШИРЕНИЕ ОБОЛОЧКИ Разработчику предлагаются некоторые возможности по модификации самой оболочки, например в проекте оболочки есть возможность изменить её название, иконку и splash screen. Однако внедрение новой логики реализуется исключительно через модули расширения. Для Visual Studio создан единый и универсальный механизм расширения, доступный в равной мере как для самой Visual Studio, так и для всех систем, построенных на базе Isolated версий её оболочки. Основным концептом расширяемости оболочки Visual Studio 2010 является так называемый VSIX-файл. Это файл, установленный в качестве расширения (extension) для выбранной вами оболочки и содержащий определённого вида манифест и бинарные коды пакетов расширения. Возвращаясь к созданной нами оболочке, VSIX-файл создаётся в результате компиляции проекта ShellExtensionsVSIX. В этом проекте наибольшего внимания заслуживает файл source.extension.manifest, в котором собрано описание VSIX-файла и всех входящих в его состав пакетов расширений. Пакеты расширения могут иметь разное назначение, и основная масса самых востребованых шаблонов собрана на диалоге 'New Project' для языков C# и VB в разделе 'Extensibility'. В этом разделе, например, есть шаблоны расширений редактора файлов, позволяющие встроить в редактор свои собственные графические и логические функции. Однако, ещё более мощным средством расширения оболочки является т.н. Visual Studio Integration Package, доступный разработчикам ещё с версии Visual Studio 2008. В созданной нами оболочке, проект VSShellStub1.AboutBoxPackage и является примером Integration Package. Integration Package позволяет реализовать: собственный пункт меню, при нажатии на который выполняется необходимое вам действие внутри оболочки (например, открытие диалога 'About Box' в нашем VSShellStub1.AboutBoxPackage) собственный Tool Window, реализующий нестандартное внутренее немодальное окно в вашей оболочке с вашим собственным устройством и фукциональностью редактор файлов, позволяющий создавать или редактировайть файлы с определённым нестандартным расширением в модифицированном под ваши нужды редакторе внутренние сервисы вашего приложения, реализующие определённую функциональность, доступную для вызова из других модулей расширения и т.п., чего впролне достаточно для большинства приложений. При создании Integration Package можно выбрать один из языков C#, VB или C++. СОЗДАЁМ СВОЙ ИНТЕГРАЦИОННЫЙ ПАКЕТ Попробуем создать свой собственный новый интеграционный пакет для нашей оболочки. Для этого в решении нажмём 'Add' -> 'New Project' -> 'Other Project Type' -> 'Extensibility' -> 'Visual Studio Integration Package'. Выберем язык C# и включим в наш пакет все три возможности: 'Menu Command', 'Tool Window' и 'Custom Editor'. Откажемся от 'Integration Test Project' и 'Unit Test Project', они нам не интересны на начальном этапе. Если вы не меняли название пакета по умолчанию, то в вашем решении появится новый проект 'VSPackage1'. Включим наш новый пакет в состав оболочки. Для этого откроем файл source.extension.manifest в проекте ShellExtensionsVSIX и нажмём 'Add Content' в разделе 'Content'. На открывшемся диалоге выберем 'VS Package' в качестве content type и проект 'VSPackage1' в качестве source. Компилируем и запускаем оболочку: в группе пунктов меню 'Tools' появился наш собственный пункт меню 'My Command name', открывающий определённое в нашем пакете сообщение в группе пунктов меню 'View' -> 'Other Windows' появился наш собственный пункт меню 'My Tool Window', открывающий определённое в нашем пакете немодальное инструментальное окно диалог 'New' -> 'File' содержит новый раздел 'VSPackage1 Files', позволяющий создать файл с определённым нами расширением *.vspackage1 и отредактировать его в его собственном редакторе Все перечисленные выше названия пунктов меню, инструментального окна, группы файлов и их расширения были сгенерированы по умолчанию при создании нашего интеграционного пакета, однако они легком могут быть заданы в процессе создания или изменены уже после этого. Приведенная процедура создания собственного расширения и включения его в состав нашей оболочки призвана продемоснстрировать достаточную простоту и наглядность этого процесса. РАЗВЁРТЫВАНИЕ ПРИЛОЖЕНИЯ Некоторого внимания заслуживает развёртывание системы, построенной на базе Isolated Shell. В Visual Studio 2008 для развёртывания и автономной работы такой системы необходима была её регистрация с помощью специально получаемых с сайта Microsoft ключей (SLK и PLK), однако в Visual Studio 2010 это требование устранено. Кроме этого, в свой инсталляционный пакет вы должны включить т.н. Visual Studio Shell (Isolated Mode) redistributable package, который обеспечивает всё необходимое окружение для запуска оболочки. После этого развёртывание системы сводится к собственно к установке вашей оболочки со всеми её расширениями. ЗАКЛЮЧЕНИЕ Пожалуй, использование Isolated Shell будет наиболее ценным для IDE-подобных продуктов, таких как дизайнеры определённых файлов, редакторы экзотических языков программирования или другие средства манипуляции наборами файлов и их содержимым, однако круг применения этого мощного средства со временем может оказаться намного шире, особенно учитывая, что Microsoft уделяет расширяемости Visual Studio с каждой версией всё больше и больше внимания.

Categories: Development | Microsoft
Posted by Vitalii Tsybulnyk on Friday, March 19, 2010 4:01 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Знания, Отношение, Способности и Привычки

Сегодня я поделюсь подходом под названием KASH box model: Knowledge / Знание – что вы знаете. Attitude / Отношение – ваше отношение со всеми лежащими в основе ценностями и выгодами. Skills / Способности – ваши возможности. Habits / Привычки – что вы на самом деле делаете. Этот подход позволяет значительно упростить понимание разрыва между знанием и деланием и всех связанных с этим проблем:  - Как часто вам приходилось видеть, как люди знают, что надо делать, но они этого не делают? Это говорит о том, что мало научить, нужно ещё и приучить.  - В большинстве случаев людей нанимают за знания и способности, а увольняют за отношение и привычки. Другими словами, многие фокусируются на знаниях и умениях, тогда как реальным тормозом развития являются отношение и привычки. Источники 1. J.D. Meier 'Career Growth and Finding Your Way Forward'

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Wednesday, January 27, 2010 6:18 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Маленькая компания vs. большая компания

В этой заметке я хочу привести и сравнить основные факторы работы в маленьких и больших софтверных компаниях. При этом критерий оценки размеров компании - вопрос весьма спорный, т.к. если, например, компания разделена на небольшине финансово- и управленчески- независимые команды со своими процессами, подходами, инструментарием и т.п., то относить такую компанию в группу больших было бы не совсем корректно. Однако такое устройство больших компаний встречается не так уж и часто, и каждый такой случай достоен индивидуального рассмотрения, так что для простоты будем иметь ввиду большие компании с единым формальным процессом работы над проектами, единым стилем управления и оценки персонала, одним и тем же набором должностей и ролей в командах и т.п. Привести какие-то оценочные цифры количества сотрудников также довольно проблематично, поэтому речь скорее пойдёт не о сравнении компании с таким-то числом сотрудников, а о тенденциях, имеющих место при сравнении компаний большего или меньшего размера. Эти тенденции более или менее однинаковы для разных масштабов сравнения, например, при сравнении работы фрилансера с работой компании из 50-ти человек, и работы компании из 50-ти человек с работой компании с 2000-ным штатом. Цель заметки - привести и сравнить как можно больше критериев, влияющих на выбор компании, а не дать итоговое сравнение "кто победил", т.к. важность определённых факторов для разных людей совершенно различна. Кроме того, даже само положительное или отрицательное значение каждого фактора весьма субъективно: например, я оценил тесные коммуникации и отсутствие формальностей как преимущество, однако я знаю примеры людей, воспринимающих это как недостаток. Фактор сравнения<- меньше компаниябольше компания -> Размер проектов (объём требований, сроки):   ? опыт прохождения полного цикла работы над проектом   ? техническая и управленческая сложность и значимость проектов   ? число разных освоенных технологий и подходов, кругозор   ? глубина овладевания и использования технологий и подходов  меньше:   + больше проектов   - ниже   + больше   - меньше  больше:   - меньше проектов   + выше   - меньше   + больше Количество людей в командах:   ? круг обязанностей каждого участника (кругозор)   ? охват ролей в проекте (возможность практиковать новую роль)   ? совершенство овладенвания своими обязанностями/ролью   ? индивидуальный вклад каждого участника   ? давление на каждого участника   ? зависимость общих результатов от каждого участника   ? оценка/самооценка сотрудников   ? вероятность быть подавленным более сильными коллегами   ? возможности менторства/помощи от более опытных коллег  меньше:   + шире   + шире   - ниже   + выше   - больше   - больше   + объективнее   + меньше   - меньше  больше:   - уже   - уже   + выше   - ниже   + меньше   + меньше   - формальнее   - выше   + больше Тяжеловесность/легковесность процессов:   ? наличие формализма и бюрократии   ? коммуникации   ? возможность оказывать влияние на процесс   ? возможность освоить проверенный эффективный процесс легковеснее:   + меньше   + теснее   + больше   - меньше тяжеловеснее:   - больше   - формальнее   - меньше   + больше  

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Tuesday, December 29, 2009 5:47 AM
Permalink | Comments (7) | Post RSSRSS comment feed

Основные антипаттерны в софтверной разработке

Антипаттерны организации и управления: Аналитический паралич (Analysis paralysis): Неоправданное внимание и затраты времени/ресурсов на стадию анализа. Дойная корова (Cash cow): Прибыльный и успешный продукт, высокая прибыль от которого зачастую приводит к чрезмерной расслабленности в разработке новых версий продукта или новых продуктов. Разработка комитетом (Design by committee): Результат вклада в разработку многих участников, но отсутствие единого видения. Эскалация обязательств (Escalation of commitment): Неспособность отказаться от решения даже когда доказана его ошибочность. Драконовские меры (Management by perkele): Авторитарный стиль управления, отвергающий инакомыслие. Moral hazard: Отделение человека, принимающего решения, от последствий этих решений. Управление грибами (Mushroom management): Стиль управления, при котором работникам предоставляется минимум информации и эта информация искажается (управлять грибами - содержть в темноте и прикрмливать навозом) . Управление основанное на числах (Management by numbers): Уделение избыточного внимания численным критериям управления, когда они неважны или стоимость их получения слишком высока Дымоход (Stovepipe): Организационная структура, при которой потоки информации циркулируют преимущественно вверх-вниз, но не горизонтально, между подразделениями. Замкнутость на продавце (Vendor lock-in): Чрезмерная зависимость системы от внешней компоненты. Сваливание расходов (Cost migration): Перенос расходов на проект к уязвимому отделу или бизнес-партнёру. Путь камикадзе (Death march): Все знают, что проект обречён, кроме главы, вплоть до "дня X". Также применяется для стиля руководства, когда сотрудники вынуждаются к сверхурочной работе для достижения нереальных сроков. Расползание рамок (Scope creep): Дозволение рамкам проекта расти без должного контроля. Groupthink: Никто не хочет выдвигать идеи, противоречащие комфортному консенсусу. Дым и зеркала (Smoke and mirrors): Демонстрация заказчику заранее заготовленных "обманок" вместо рабочей функциональности. Раздувание ПО (Software bloat), Функции для галочки: Каждая следующая версия продукта требует всё больше системных ресурсов без явной выгоды для пользователя. Ползущий улучшизм (Creeping featurism): Добавление новых улучшений в ущерб качеству системы. Продолжительное устаревание (Continuous obsolescence): Выделение непропорционально больших усилий портированию системы в новые окружения. Bystander apathy: Дизайн или требования неверны, но те, кто это знают, ничего не предпринимают по этому поводу, т.к. для этого необходимо вовлечение большего числа людей. Tester Driven Development: Новые требования к продукту возникают из отчётов об ошибках. Я тебе это говорил (I told you so): Когда игнорируется предупреждение эксперта, являющееся оправданным Единственный знающий человек (Single head of knowledge): ЕЗЧ (SHOK) применим в том случае, когда единственная личность во всей организации контролирует жизненно-важную область ноу-хау или информации о внутренностях системы. Рыцарь на белом коне (Knight in shining armor): РНБК (KISA) происходит тогда, когда личность, которая не совершает ошибок, появляется на сцене и пытается починить всё, без сообщений о том, какие изменения он/она сделал/сделает и почему. Gold plating: Работа над проектом после момента, когда уже усилия перестают приносить прибыль или создавать добавочную стоимость. Антипаттерны дизайна и реализации:  Большой комок грязи (Big ball of mud), Проблема йо-йо (Yo-yo problem), Спагетти-код (Spaghetti code): Структура системы отсутствует или трудно поддаётся пониманию. Бензиновая фабрика (Gas factory), Ненужная сложность (Accidental complexity), Inner-platform effect, Раздувание интерфейса (Interface bloat): Неоправданное усложнение дизайна системы, излишняя гибкость или универсальность. Инверсия абстракции (Abstraction inversion): Не предоставление реализованных функций, необходимых пользователям, что вынуждает их реализовывать эти функции заново с помощью функций более высокого уровня. Database-as-IPC: Использование базы данных для обмена соосбщениями между процессами там, где можно использовать более легковесные способы. Затычка на ввод данных (Input kludge): Отсутствие коректной обработки возможного неверного ввода. Магическая кнопка (Magic pushbutton): Написание бизнес-логики в коде пользовательского интерфейса (например в обработчике события нажатия на кнопку). Гонки (Race hazard):Ошибка в определении последовательности различных порядков событий. Базовый класс-утилита (BaseBean): Наследование класса-утилиты вместо делегирования к нему. Вызов предка (Call super): Для реализации прикладной функциональности методу класса-потомка требуется в обязательном порядке вызывать те же методы класса-предка. Circular dependency: Ненужная прямая или непрямая взаимная зависимость между объектами или модулями. Блоб (Blob), Божественный объект (God object): Концентрация слишком большого количества функций в одиночной части дизайна (классе). Объектная клоака (Object cesspool): Повторнае использование объектов, чьё состояние не удовлетворяет (возможно неявным) условиям повторного использования. Паблик Морозов (Object orgy): Предоставление неоправданного доступа к внутренним свойствам объекта. Полтергейст (Poltergeists): Объекты, чьё единственное предназначение — передавать информацию другим объектам. Sequential coupling: Класс, требующий вызова его методов в строго определённом порядке. Действие на расстоянии (Action at a distance): Неожиданное взаимодействие между далёкими частями системы. Накопить и запустить (Accumulate and fire): Установка параметров подпрограмм в наборе глобальных переменных. Слепая вера (Blind faith): Недостаточная проверка корректности исправления ошибки или результата работы подпрограммы. Лодочный якорь (Boat anchor): Сохранение более не используемой части системы. Активное ожидание (Busy spin): Потребление ресурсов процессора во время ожидания события, обычно при помощи постоянно повторяемой проверки, вместо того, чтобы использовать систему сообщений. Cargo cult programming: Использование паттернов и методик без понимания причин. Проверка типа вместо интерфейса (Checking type instead of membership, Checking type instead of interface): Проверка того, что объект имеет специфический тип в то время, когда требуется только определённый интерфейс. Инерция кода (Code momentum): Сверхограничение части системы путём постоянного подразумевания её поведения в других частях системы. Кодирование путём исключения (Coding by exception): Добавление нового кода для поддержки каждого специального распознанного случая. Таинственный код (Cryptic code): Использование аббревиатур вместо мнемоничных имён. Error hiding: Перехват сообщения об ошибке до того, как она показывается пользователю, в следствие чего пользователь не получает сообщения об ошибке или получает бессмысленное сообщение. Expection handling: Использование системы исключений для реализации бизнес-логики системы. Жёсткое кодирование (Hard code): Внедрение предположений об окружении системы в слишком большом количестве точек её реализации Мягкое кодирование (Soft code): Патологическая боязнь жёсткого кодирования, приводящая к тому, что настраивается всё что угодно, при этом конфигурирование системы само по себе превращается в программирование. Поток лавы (Lava flow): Сохранение нежелательного (излишнего или низкокачественного) кода по причине того, что его удаление слишком дорого или будет иметь непредсказуемые последствия. Loop-switch sequence: Кодирование последовательности шагов с помощью цикла и оператора выбора (switch). Магические числа (Magic numbers): Включение чисел в алгоритмы без объяснений. Программирование методом копирования-вставки (Copy and paste programming): Копирование (и лёгкая модификация) существующего кода вместо создания общих решений. Дефакторинг (De-Factoring): Процесс уничтожения функциональности и замены её документацией. Золотой молоток (Golden hammer, Silver bullet):  Сильная уверенность в том, что любимое решение универсально применимо. Фактор невероятности (Improbability factor): Предположение о невероятности того, что сработает известная ошибка. Преждевременная оптимизация (Premature optimization): Оптимизация на ранних стадиях в ущерб хорошему дизайну, сопроводимости и иногда даже реальной эффективности системы. Programming by permutation (или "programming by accident"): Попытка достижения нужного результата путём последовательного изменения кода и проверки помогает ли это. Изобретение колеса (Reinventing the wheel): Разработка собственного решения вместо применения существующего. Изобретение квадратного колеса (Reinventing the square wheel): Создание собственного плохого решения, когда существует хорошее. Ад зависимостей (Dependency hell), DLL-ад (DLL hell): Проблемы с совместно испльзуемыми билиотеками по причине различий в версиях одной и той же библиотеки   Источники 1. Anti-pattern on 2. Антипаттерн на

Posted by Vitalii Tsybulnyk on Tuesday, December 22, 2009 4:27 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Автоматическое тестирование UI от Microsoft

Вопрос автоматического тестирования пользовательского интерфейса (UI) по праву считается самым сложным аспектом контроля качества софтверных продуктов. И сложность здесь заключается не только в многообразии пользовательских сценариев и чисто "визуальном" отображении информации, а также и с отсутствием простых и одновременно надёжных инструментов и фреймворков для автоматического тестирования UI. Что же на этом поприще может предложить Microsoft, как "гигант" и "флагман" индустрии? К сожалению, для классических Win32 приложений Microsoft не предлагает ничего, достойного внимания профессионального тестировщика. Однако с появлением .Net Framework (а в особенности WPF) ситуация радикально меняется к лучшему, и иначе как революционным решение Microsoft для managed UI automation я назвать не могу. Заинтересовавшиеся могут сами ознакомится с возможностями System.Windows.Automation, скажу лишь что по надёжности и простоте Вы врядли найдёте что-то лучшее для автоматизации QA десктоп-приложений. Что же касается web, то на рынке уже есть несколько неплохих продуктов для автоматического тестирования веб-интерфейсов, однако для тех, кто работает с технологиями Microsoft, и в частности ASP.NET, советую обратить пристальное внимание на достаточно новую разработку Lightweight Test Automation Framework. Неоспоримыми достоинствами и залогом будущего успеха являются простота и плотная интеграция продукта непосредственно с ASP.NET.

Categories: Development | Microsoft
Posted by Vitalii Tsybulnyk on Wednesday, December 9, 2009 10:33 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Software Quotes

UNIX is simple. But It just needs a genius to understand its simplicity. -Dennis Ritchie   Before software can be reusable, it first has to be usable. -Ralph Johnson   Good judgment comes from experience, and experience comes from bad judgment. -Fred Brooks   It's hard enough to find an error in your code when you're looking for it. It's even harder when you've assumed your code is error-free. -Steve McConnell Code Complete   The trouble with the world is that the stupid are sure and the intelligent are full of doubt. -Bertrand Russell   If debugging is the process of removing bugs, then programming must be the process of putting them in. -Edsger Dijkstra   You can either have software quality or you can have pointer arithmetic. You cannot have both at the same time. -Bertrand Meyer   There are two ways to write error-free programs; only the third works. -Alan J. Perlis   Measuring programming progress by lines of code is like measuring aircraft building progress by weight. -Bill Gates   The first 90% of the code accounts for the first 10% of the development time. The remaining 10% of the code accounts for the other 90% of the development time. -Tom Cargill   Programmers are in a race with the Universe to create bigger and better idiot-proof programs. The Universe is trying to create bigger and better idiots. So far the Universe is winning. -Anonymous   Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why it works. Programmers combine Theory and Practice: Nothing works and they don't know why. -Anonymous   The Six Phases of a Project: 1.  Enthusiasm 2.  Disillusionment 3.  Panic 4.  Search for the Guilty 5.  Punishment of the Innocent 6.  Praise for non-participants -Anonymous

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Tuesday, October 27, 2009 5:57 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Побеждаем ошибки

Я давно наблюдаю за тем, как люди допускают ошибки. И чем больше я это делаю, тем больше меня удивляет не то, что большинство людей (и я в том числе) допускает их постоянно. Самое странное для меня то, что многие люди каждый раз искренне удивляются, допуская ошибку: "Как это могло произойти? Как я мог этого не заметить / об этом не подумать?". И дальше происходит самое страшное: "Больше такого со мной не случится! Я буду внимательнее / дальновиднее / аккуратнее". Потом ошибки допускаются снова и всё повторяется. В результате ошибок не становится меньше, зато падает самооценка и мотивация. Лично я так не делаю и вам не советую. Лично я знаю точно, что я ошибаюсь, что к большому моему сожалению непогрешимость не входит в число моих талантов, как впрочем и в число талантов большинства знакомых мне (даже очень талантливых) людей. И я использую это знание: я никогда не делаю ставку на безошибочность свою или людей, с которыми я работаю. Как раз наоборот, я стараюсь всегда исходить из того, что если ошибка может произойти, то рано или поздно она происходит, поэтому я делаю всё возможное для того, чтобы ошибке негде было случиться:  - я не полагаюсь на свою память, если нужно что-то "просто запомнить", то такое решение скорее всего не для меня;  - я не полагаюсь на свою внимательность, например задачу типа "внимательно просмотреть" я стараюсь заменить на "использовать автоматическое средство";  - я никогда не заливаю исправление в коде (даже если это одна буква), предварительно не скомпилировав его и не проверив работоспособность и т.п. Конечно, бывают в жизни случаи, когда соблюдение вышеперечисленных правил не представляется возможным. Однако я продолжаю следовать своему правилу: я никогда не удивляюсь ошибкам (своим или чужим) и никогда не обещаю (и не требую) безошибочной работы. То, чего я требую от себя и от других, как раз прямо противоположно этому: никогда не полагаться на непогрешимость человека, а делать всё возможное для того, чтобы ошибке просто негде было произойти.

Categories: Development | Management
Posted by Vitalii Tsybulnyk on Wednesday, September 16, 2009 6:10 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Основы юнит-тестирования

Несмотря на то, что повсеместные гимны юнит-тестированию отзвучали уже лет 10 назад, и в настоящее время следование практике юнит-тестирования стало составляющей общей грамотности разработчиков, довольно часто приходится встречать команды и отдельных разработчиков, которые этой практике не следуют. Происходит это потому, что навыки грамотного юнит-тестирования относятся к навыкам "с отложенным результатом", т.е. усилия вы предпринимаете сейчас, а результат получаете потом, в процессе сопровождения, доработки и регрессионного тестирования кода. Таким навыкам очень сложно научиться самому, т.к. только на опыте работы команды можно почувствовать балланс между затраченным на юнит-тестирование временем и полученным от него результатом. Именно поэтому внедрение практики юнит-тестирования - задача прежде всего технического лидера команды, а наличие в команде специалиста с предыдущим успешным опытом в этой области ускоряет такое внедрение в разы. Тем не менее, наличие инструктора не отменяет знания основ грамотного юнит-тестирования, чему я и решил посвятить этот пост. Итак, хорошие юнит тесты: Автоматизированы Выполняются быстро: выполнение сотни или даже тысячи юнит-тестов должно занимать считанные секунды Написаны в рамках эффективного фреймворка Независимыми друг от друга Результат работы теста воспроизводим и повторяем Легко поддаются отладке Написаны автором кода Оставляют конфигурацию / окружение в неизменном состоянии Имеют высокое покрытие кода (code coverage): при создании юнит-теста важно выполнить каждую строчку тестируемого кода и убедиться что все возможные условия протестированы. Поддаются хранению и сопровождению Тестируют как функциональность, так и аварийные ситуации: т.н. "позитивные" тесты подтверждают, что метод работает корректно в ожидаемых условиях, а "негативные" тесты проверяют что метод корректно обрабатывает нержиданные или критические условия Покрывают граничные значения входных параметров: посхольку дефекты часто имеют место на границах, хоршей стратегией есть покрытие значений немного не доходящих до граничных, равных граничным, и немного превосходящих граничные. Юнит-тесты имеют и некоторые органичения, о которых тоже нужно помнить: Юнит-тестирование не находит все ошибки в коде: оно показывает только наличие ошибок, а не их отсутствие У юнит-тестирования ограниченные рамки: это тестирование «белого ящика» Юнит-тестирование не покрывает сценарии и интеграцию между компонентами Одной из наиболее важных техник, которые позволяют создать хорошие юнит-тесты, является техника использование mock-объектов (mock objects). Mock-объект - это симуляция реального объекта там, где использование реального объекта невозможно или нарушает принципы юнит-тестирования, например когда реальный объект: предоставляет недетерминированные результаты (например текущее время или температуру) имеет трудно воспроизводимые состояния (например ошибка сети) медленный (например полная база данных или файл на диске) ещё не существует или может изменить поведение должен содержать информацию или методы, необходимые только для тестирования

Categories: Development
Posted by Vitalii Tsybulnyk on Friday, August 21, 2009 1:57 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Рефакторим базу данных

Последние годы техника рефакторинга настолько прочно вошла в методологии процессов разработки ПО и инструментарий разработчиков, что всё чаще и чаще звучат утверждения о начале эры принципиально новых, эволюционных подходов к проектированию архитектуры. Пожалуй, одной из немногих областей, которая ещё прочно держит позиции предварительного проектирования, является структура базы данных. Действительно, изменение структуры базы данных по ходу жизненного цикла сопряжено с рядом существенных струдностей и затрат: это и миграция данных, и необходимость каскадного изменения кода приложений, использующих базу данных, и ряд других объективных трудностей. Однако, прогресс не стоит на месте, мыслители и идеологи рефакторинга и гибких методолий конечно же не мирятся с таким упущением. Наглядное тому подтверждение - некоторые книги и статьи Мартина Фаулера и его соратников. Одна из первых таких публикаций - это статья Фаулера 'Evolutionary Database Design', которая собственно и натолкнула меня на написание данного поста. Прежде чем говорить о применении техник рефакторинга по отношению к базам данных, нужно упомянуть некоторые ограничения, выход за рамки которых может существенно затруднить или даже сделать невозможными эти техники: 1. База данных исполюзуется в одном приложении или системе, это не интегрированная база данных для многих систем. 2. База данных не должна работать бесперебойно 24/7 Если данные условия соблюдены для вашего случая, можете смело рассчитывать применять к своей базе данных все те же подходы, которые уже успрешно применяете для всего остального кода проекта. Вот некоторые детали реализации рефакторинга применительно к базе даннных: 1. DBA и девелоперы должны очень тесно сотрудничать, т.к. рефакторинг базы данных с большой вероятностью влечёт изменения кода. Устраните все физические, психологические и бюрократические препятствия на пути их сотрудничества. Лично я всегда предпочитал DBA и девелопера в одном лице, котя конечно же это далеко не всегда целесообразно и возможно. 2. У каждого участника процесса есть своя копия базы данных для експериментов по нахождения оптимального рефакторинга. 3. Тестовая база данных - это не просто схема, она также содержит тестовые данные, близкие к реальным. Рефакторинг базы данных - это не только изменение схемы, он зачастую требует миграции и т.п. работы с данными. Чем больше данных содержит ваша тестовая база данных, тем более гладко пройдёт рефакторинг на продакшн базе. 4. Все изменения в базе данных по ходу работы над проектом - это рефакторинги, поэтому применяйте к ним те же шаги и правила, что применяете к обычному рефакторингу (см. Martin Fowler 'Refactoring: Improving the Design of Existing Code') 5. Автоматизируйте свой рефакторинг по окончанию работы над ним: сохраните скипт, производящий ваш рефактронг, с тем чтобы простым запуском этого скрипта вы могли выполнить рефакторинг на любой из копий базы данных, включая продакшн. 6. Сообщайте о изменнениях в базе всем разработчикам, лучше через автоматическую отправку е-мейла. 7. Выделяйте в своей системе явно выраженный слой доступа к данным, это позволит свести к минимуму последствия рефакторинга базы для остального кода (воспльзуйтесь одним из паттернов, описанных Фаулером в 'Patterns of Enterprise Application Architecture'). Ну и напоследок, хороший предварительный дизайн базы данных - это бесспорно очень хорошее начало для любого проекта. Однако последующие изменения неизбежны, и в нех нет абсолютно ничего страшного. Эволюционное изменение базы данных по ходу проекта не только уменьшит для вас затраты на предварительный дизнайн, но и избавит ваших разработчиков от необходимости подстраиваться под неудачный или устаревший дизайн базы данных. Следуйте приведённым выше рекомендациям и изменение базы данных превратиться для вас из страшилки для новичков в обыденную работу над доведением системы до идеала.

Posted by Vitalii Tsybulnyk on Tuesday, August 11, 2009 4:25 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Проектирования больше нет?

Martin Fowler (Мартин Фаулер) бесспорно является одним из самых уважаемых авторов в области современного проектирования и архитектуры программных продуктов. Его бестселлеры 'Refactoring: Improving the Design of Existing Code' и 'Patterns of Enterprise Application Architecture' - это, пожалуй, наиболее ценные книги, прочитанные мною за всю мою профессиональную жизнь. Недавно мне в руки попала замечательная статья Мартина с броским названием 'Is Design Dead?' (в русском переводе "Проектирования больше нет?"), о которой сегодня и пойдёт речь. Основная идея статьи - обсудить изменения в подходах к проектированию программных систем в связи с переходом к гибким (Agile) методологиям. Провокационное название статьи отражает тот факт, что многие Agile методологи (в первую очередь XP) преподносят дизайн системы как нечто возникающее эволюционно, в процессе непосредственного кодирования: Методология XP бросила вызов многим устоявшимся представлениям о разработке программного обеспечения. Пожалуй, наиболее противоречивой идеей является отказ от предварительного проектирования в пользу более эволюционного подхода. Для приверженцев новой методологии, это отказ от техник проектирования (например, UML), их принципов и паттернов. Незачем беспокоиться о проектировании, считают они. Достаточно внимательно "вслушиваться" в свой код, и проектирование образуется само собой. Фаулер, как выдающийся специалист в области проектирования, конечно же не соглашается с таким утверждением: В большинстве случаев, эволюционное проектирование - это нечто ужасное. В конце концов, все равно вместо дизайна системы вы получаете просто набор из специфических решений, каждое из которых затрудняет дальнейшие изменения в программном коде. Часто это вообще нельзя считать дизайном (и, уж конечно, такой дизайн никак нельзя назвать хорошим). Как говорит Кент, дизайн существует для того, чтобы дать возможность оперативно вносить в систему любые изменения. Если дизайн плох, то такая возможность исчезает. В результате вы будете иметь дело с энтропией программного продукта, и со временем и без того плохой дизайн системы станет еще хуже. Теперь вам будет не только сложнее вносить в систему изменения, но и отыскивать и исправлять ошибки, которые начинают множиться с катастрофической быстротой. Все это - кошмар разработок в стиле "code and fix", когда с течением времени исправление ошибок обходится все дороже и дороже. Однако одновременно являясь ярым приверженцем Agile и автором "библии" рефакторинга, Фаулер признаёт и рекламирует их эффективность: В методологии XP имеется много спорных моментов. Одним из ключевых таких моментов является то, что она базируется на эволюционном, а не предварительном проектировании. В основе этого утверждения лежит кривая стоимости изменений в программном продукте. XP строится на предположении, что эту кривую можно сгладить до такой степени, чтобы можно было применять эволюционное проектирование. Такое сглаживание, с одной стороны, возникает при использовании методологии XP, а с другой, оно же в ней и используется. Это еще раз подчеркивает тесную взаимосвязь между практиками ХР: нельзя использовать те части методологии, которые предполагают существование сглаживания, не используя те практики, которые это сглаживание осуществляют. У практик, с помощью которых осуществляется сглаживание, есть множество составляющих. В основе всех их лежит Тестирование и Непрерывная интеграция. Именно надежность кода, которую обеспечивает тестирование, делает возможным все остальное в этой методологии. Подобный эффект имеет и рефакторинг. В статье Фаулер пытается найти компромис, балланс между традиционными (и бесспорно необходимыми) методиками проектирования с одной стороны и Agile с другой: Джим Хайсмит ... использует аналогию с обычными весами. На одной чаше лежит предварительное проектирование, на другой - рефакторинг. В более традиционных подходах к разработке ПО перевешивает предварительное проектирование, так как предполагается, что передумать вы не можете. Если же стоимость изменений снизится, то часть проектирования можно делать и на более поздних стадиях работы, в виде рефакторинга. Это вовсе не означает отказа от предварительного проектирования. Однако теперь можно говорить о существовании баланса между двумя подходами к проектированию, из которых можно выбрать наиболее подходящий. Все эти основополагающие практики (непрерывная интеграция, тестирование и рефакторинг) создают новую среду, в которой эволюционное проектирование выглядит вполне убедительно. Впрочем, мы еще не выяснили, где же у этих весов точка равновесия. Лично я уверен, что не смотря на поверхностное впечатление, методология ХР - это не просто тестирование, кодирование и рефакторинг. В ней найдется место и для предварительного проектирования. Частично оно производится еще до написания первой строчки кода, но большая его часть приходится на то время, которое предшествует реализации конкретной задачи в течение итерации. Впрочем, такая ситуация представляет собой новое соотношение сил между предварительным проектированием и рефакторингом. Собственно, вся статья и посвящена нахожденю этого компромисса. Показывается полезность и органичность предварительного проектирования в XP, преимущества и критерии простого дизайна перед сложным при условии следования всем остальным практикам XP, показывается эффективное сосуществование принципа YAGNI ("You Aren't Going to Need It" - "Это вам не понадобится") и рефакторинга, применимость и ценность паттернов проектирования и даже UML в XP. Пожалуй я воздержусь от приведения здесь заготовленных мною цитат из статьи, а закончу пост настоятельной рекомендацией причитать эту статью. Она как никакая иная ценна для опытных разработчиков, архитекторов и менеджеров, переходящих на Agile методологии и имеющих какие-то сомнения по применимости своих знаний и умений в новых условиях. Статья не мене полезна и тем, кто имеет большой опыть например в XP, но не имеющих базисных знаний и умений в предварительном проектировании. И пожалуй наиболее полезна статья тем, чьи знания, умения и опыт равноценны в обеих сферах, т.к. изложенные концепции позволят наиболее эффективно и гармонично использовать и сочетать все эти бесценные умения в вашей работе.

Posted by Vitalii Tsybulnyk on Wednesday, July 22, 2009 7:06 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Call Java code from .Net and vice versa

This post is about the very common problem of .Net and Java code interoperability. I met this problem at least twice, both times when a .Net application, which is already developed, was required to use some third-party Java API. So let me introduce you the best solution I've ever seen: JNBridge. Here is a very nice presentation made especially for Microsoft Visual Studio team: JNBridge.wmv (6.78 mb) Just a couple of slides from this presentation to let you realize the power of JNBridge: The most impressive feature for me is the possibility to use .Net and Java code in one process via shared memory, however HTTP/SOAP connection is also a very useful option for distributed solutions. JNBridge has a plugin for Visual Studio and Eclipse which allows you to effectively work with the tool in both IDEs.

Categories: Development
Posted by Vitalii Tsybulnyk on Wednesday, June 24, 2009 11:27 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Visual Studio on Channel 9

This post is just to let you know that there is 'Visual Studio' topic area on  MSDN Channel 9. Here is the list of my favorite episodes: • C# 4.0 - Questions and reasons behind the answers • Team Foundation Server 2010 • Enterprise Project Management with Visual Studio Team System 2010 • Web Development and Deployment with Visual Studio 2010 • Debugging Parallel Applications with Visual Studio 2010 • Visual C++ 10: 10 is the new 6 • The Future of Visual Studio Extensibility

Categories: Development | Microsoft
Posted by Vitalii Tsybulnyk on Friday, June 12, 2009 6:08 AM
Permalink | Comments (0) | Post RSSRSS comment feed