I like real world statistics. Here is a programming languages popularity comparison by Tiobe Software.
I'm going to start new fun project - Rubik's Cube. Eiffel Envision + .NET + NUnit + DirectX 9.0. Tools Envy ®.
Today, while downloading dx9sdk (225 MB), managed to create first test. Gotchas:There is also Agile Data Homepage by Scott W. Ambler. Lot of useful information, but maybe bit superfluous, especially for me right now. BTW, Scott W. Ambler's Agile Modelling mailing list was my last step before diving into XP.
Cover scan and other relevant changes in Books.
Downloaded Glowcode. Looked good - small and humble. Crashed every time when starting to profile. Uninstall.
DevPartner Profiler. Integrates (hides) into MS VS. Required to build my program with special profile data.
It worked for debug configuration, but failed with release build. Uninstall.
100 MB VTune. Last chance, better be good. And it really good. After I figured out linker "/fixed:no" option,
rebuilt application and profiled I got my bottleneck (as usual it wasn't that I thought of) and reduced it
to reasonable level. BTW, memory mapped file was approximately 3 times faster then fseek/fread in this case.
How it works. News stored in xml file. News filtering and presentation done via xsl. Cookie with last_read_id stored and retrieved by scripts and passed as parameter to xsl (because xsl can't do it itself).
Page has 3 modes of operation:Big XP projects with tens of developers are very rare. And so Martin's management experience is invaluable. Usual planning discussions on groups are quite simple and miss (as I see now) many important points. I definitely need some planning experience and then I'll read this book one more time.
Relevant changes in Books.3 weeks elapsed since I announced Rubik's Cube project. Time to ship something. Release 1 placed at the bottom of Code section. ebcl.dll (standard Eiffel runtime?) is 13.5 MB in size, that's why executable package is so big. You can run tests yourself from exe file using NUnit. Of course there is full source code written (rewritten from ### see my previous post) according to resume-quality and TDD principles. For all Eiffel discrepancies you should blame me (not Chet and nor Bertrand).
Stories that I tried, but failed to implement:Well, "more features to come" and I hope to unleash power of DBC in most appropriate language.
assert(resample([0 1 2 3 4], 2) == [0 2 4])
Test fails, code the simplest thing
function result = resample(input, new_step)
result = 0 : 2 : 4
function result = resample(input, new_step)
result = input(1) : new_step : input(length(input))
Instead of removing duplication we could use triangulation
assert(resample([2 3 4], 2) == [2 4], 'second first element')
assert(resample([0 1 2], 2) == [0 2], 'second last element')
assert(resample([0 1 2 3 4 5 6], 3) == [0 3 6], 'second new step')
function result = resample(input, new_step)
result = input(1) : new_step : input(length(input))
Tests pass, done.
From Kent's TDD book draft: "Triangulation feels funny to me. I only use it when I am completely unsure of how to refactor. If I can see how to eliminate duplication between code and tests and create the general solution, I just do it.Why would I need to write another test to give me permission to write what I probably could have written the first time?Here is my pros for triangulation and cons against first approach:
More than appropriate here a Writing as a Reflective Practitioner with Wisdom (beware unclosed header tag).
See also Top 10 tricks used by recruitment agencies!.
My projects really lack AT and I'm going to bring the customer closer to the development team. Teach her and help her create these testing scenarios.
Very interesting and easy to read paper on software economics Towards Measuring Software Value (you can hover mouse over indices to read notes) by Howard Baetjer.
"for reasons I will never understand, testers actually seem to enjoy this kind of thing" wrote Ron Jeffries about QA. You can see it for yourself in Test aerobics clip (9.5 MB) by James Whittaker.Two sites about non-standard job searching techniques: JobHuntersBible by Dick Bolles author of "What Color Is Your Parachute?" and Ask The Headhunter .
int signal_attenuation(){ const int maxThreshold = 42; int result = free_space_attenuation(); if (result >= maxThreshold) return maxThreshold; result += obstacles_attenuation(); if (result >= maxThreshold) return maxThreshold; ENSURE(result <= maxThreshold); return result; }Code above is untestable. OK, here goes second version.
typedef int (*IntFunction)(); int signal_attenuation(int maxThreshold, IntFunction free_space_attenuation, IntFunction obstacles_attenuation){ int result = free_space_attenuation(); if (result >= maxThreshold) return maxThreshold; result += obstacles_attenuation(); if (result >= maxThreshold) return maxThreshold; ENSURE(result <= maxThreshold); return result; }Much better. We can even use boost::function.
int signal_attenuation(int maxThreshold, boost::function<int> free_space_attenuation, boost::function<int> obstacles_attenuation){ ...The problem is we don't need all this flexibility. Nobody will pass different parameters to our function in runtime. Production code and tests already determined. So, the last version.
template <int maxThreshold, class FreeSpaceAttenuation, class ObstaclesAttenuation> int signal_attenuation(){ int result = FreeSpaceAttenuation::free_space_attenuation(); if (result >= maxThreshold) return maxThreshold; result += ObstaclesAttenuation::obstacles_attenuation(); if (result >= maxThreshold) return maxThreshold; ENSURE(result <= maxThreshold); return result; } class MockFreeSpaceAttenuation{ public: static int free_space_attenuation() const{ return 1; } };I'm glad to be able to express my design decisions in program code.
For detection I used _CrtMemCheckpoint and _CrtMemDifference functions from Debug version of C run-time libraries. First checkpoint placed before first test and second after the last. No need to change other code or project settings. It becomes a little trickier if you want to suppress Release build warnings or wrap this API in elegant class, but doable (although I failed to get memory leak size).
Yesterday installed Cincom Smalltalk. I already have a little experience with Squeak and now I'm reading Ivan Tomek's introduction. For me the different kinds of messages and their precedence were most confusing and this tutorial clears it in a moment.
Tomorrow I will promote acceptance tests first practice to direction.
One lesson for me - continuous communication is the key. Rare meetings are bad time to introduce new ideas, cause everybody have accumulated they own thoughts and want to talk more then listen.
"I don't always use TDD for throwaway code. When I don't, I almost always get in trouble and have a long debugging session. Slow learner." Ron Jeffries.
"If something (good) hurts, do it more often."
Using MS Visual Studio .NET and Visual Assist .NET for C++ projects, here is a list of functions (which use current text cursor position) that I have key bindings to:
Copy line to clipboard | Handwritten macro |
Paste line from clipboard below current line | Handwritten macro |
Open line up/down to current (similar to Home/End + Enter) | Handwritten macro |
Delete line | MSVS |
Comment/uncomment block | MSVS |
Increase/decrease indent | MSVS |
Go to function/class definition | VA |
Previous location (similar to back in IE) | VA |
Build+run tests/run | MSVS |
Open alternative file(.h from .cpp and .cpp from .h) | VA |
Other important features are auto completion and syntax highlighting (VA), tabs (similar to Netcaptor or MyIE) (MSVS), templates for class/test/function files creation (handwritten wizards).
In gVim (for Clipper/FoxPro projects) I additionally have "find same words and mark it" feature, just click the word to find holding Shift. Actually, it was the gVim that converted me. No need for toolbars and menus any more.I'm now using VisualWorks 7 a little for personal project. You know "Smalltalks' IDE are best". Well, I'll say you this: default configuration is ... questionable. Different windows (9 to the moment) clutter my taskbar, no user friendly toolbar, menu, key bindings customization. Good news: there are parcels for syntax highlighting, autocompletion, tabs. Today I hacked through to add "go to class in one key" feature. Something like "change your environment".
Programming patterns?
How it works:
1. There is no "tomorrow". Free time doesn't grow on trees.
2. More early is's fixed, more early you'll start to get benefits.
3. Quality work has strong positive feedback. And vice versa.
Which approach is better? I prefer the latter. Former looks more efficient, but to solve a problem is not enough. Do we need this solution at all? Do we need toolbar, what size of the window we want, is this a right test? We should think about it and interacting with an environment is not the best way of thinking for me. Fast feedback is important, but first define the goal.
What if we don't know what we want? Well, it's another question...I have a little experience using Windows Media Encoder 9 and this is how it works. I also recommend to download Window Media Player 9, it required for video editing and seems to have most recent codecs. I'm using Windows XP, but theoretically it should work under Windows 2000 as well. I'm using Genius Mic-01A microphone with frequency response from 100 Hz to 10 KHz and it sounds great. During recording my Athlon XP 1.667 GHz loaded up to 100% (70% on average).
Settings for WME9: Start from "Capture Screen" Wizard, capture "entire screen" and "audio", choose "high" quality, don't "begin capturing" and just click on "Finish". Go to "Properties", go to "Compression" tab and click "Edit", select "Quality VBR" video mode, go to "Quality-based" tab, select "Audio format" 16 kbps 22 kHz mono CBR, enter "Frame rate" 5 fps, go back to "General" tab, enter your favorite "Name" and "Export..." to unique profile file (otherwise some of your encoding settings will not be saved), press "OK" on the whole "Custom Encoding Settings" dialog. Now "Save" your session in file, next time just click this ".wme" file and you are ready to go!A picture is worth 1000 words, so check the bottom of Code section. There is little programming experience in that file, but you can check quality of picture and sound. You can also use such recordings for personal reflections <g>.
Without specification there is no correctness. Maybe this is the way to fight against "code first".
"... the programmers did not commit a bug. The team didn't do the right thing, it is true, but the problem starts with a missing Customer Test." Ron Jeffries.
What is your choice? Should we trust programmers or should we write more tests? Probably your don't have to make a choice. If you are a developer or a manager then trust, but when you are a customer then better check.When I first saw and tried CppUnit, the need to open test dialog somehow and click "Run" button every time I test was the reason I created my own UT framework that runs from command line and just displays assertions result in Windows MessageBox. I used the same approach creating UT framework for Clipper.
Then Eiffel and NUnit. I like NUnit's ability to collect tests from the program via attributes (no need to manage tests inside program). And we can start NUnit only once, later just clicking on "Run" button. NUnit also has assertEquals (to programmatically display nice descriptions like "Expected 1, but was 2.") and able to catch unhandled exceptions (to continue run other tests).Then VisualWorks and SUnit. Lack of description in assertions is my main objection (SUnit 3.1 has descriptions, but it displays them in common launcher window and so they are ineffective). Despite that SUnit has several neat features such as time elapsed from the last successful run, number of tests and yellow background while running tests.
In my recent Matlab UT framework I'm trying to combine these best practices, particularly creating a large set of equals assertions comparing matrices and signals with graphical descriptions. And now I'm back to the problem of one button testing. Maybe it's not a problem in VisualWorks where SUnit window is small and just one of the other 10, so we can constantly keep it near the corner of the screen. But using MS VisualStudio I can do my work having only one active window containing program code. I don't like to have to take a mouse, drag cursor to taskbar, select UT Gui window and click "Run" in it.Definitely there are programs to automate such tasks (I even wrote one myself), for example Tasker that I'm using right now. But I think it would be better if UT frameworks developers build some interfaces (COM, command line) into the program to facilitate true one key press operations.
Two most interesting things for me in this release are BOOST_CURRENT_FUNCTION macro similar to __FILE__ and __LINE__ (it works in vc7) and Filesystem Library.
WindowsXP controls in VW 7.1 looks little inappropriate as I use classic Windows scheme. Old windowSpec of my main window failed to load in v7.1, so I recreated it from scratch. To successfully deploy I included Toolbar resources in project (it used when you have a menu in program). Also I created separate image for deployment and I hope it will lighten the process (but definitely not to the level I have in C++). Testing using ForkedUI seems to cease to work too, but now I know that mixing acceptance testing with unit testing isn't a good idea anyway and I will try to use external tool such as TestComplete.
Removed link to Joel on Software (everybody knows about him without me and it's not so interesting now). Added link to just discovered Agile Articles (lot of resources divided by categories for easy search).
Added blogs section featuring Laurent Bossavit, Keith Ray and Brian Marick.Added agile-testing yahoo group (posters include Bret Pettichord, Lisa Crispin, Elisabeth Hendrickson, Cem Kaner from a testing world as well as many known leaders of agile community). Removed Boost Users group as of little value, particularly for the reader of the main Boost (developers) group.
Added Matlab newsgroup to the list. It's my champion newsgroup for high traffic and time I spend reading it (I'm newbie, Matlab is very big and there is absolutely no flame, just Q&A).Transaction class>>newWithAmount: aQuantity from: fromAccount to: toAccount whenCharged: aTimepointOrDate ^self newWithAmount: aQuantity from: fromAccount to: toAccount whenCharged: aTimepointOrDate creator: nil sources: Set new newWithAmount: aQuantity from: fromAccount to: toAccount whenCharged: aTimepointOrDate creator: aPostingRule sources: aSetOfEntries ^self new setAmount: aQuantity from: fromAccount to: toAccount whenCharged: aTimepointOrDate creator: aPostingRule sources: aSetOfEntries Transaction>>setAmount: aMoney from: aDebitAccount to: aCreditAccount whenCharged: aTimepointOrDate creator: aPostingRule sources: aSetOfEntries "private" self require: [aMoney isKindOf: Money. aDebitAccount isKindOf: ServiceAccount. aCreditAccount isKindOf: ServiceAccount. (aTimepointOrDate isKindOf: Date) or: [aTimepointOrDate isKindOf: Timepoint]. (creator == nil) or: [creator isKindOf: PostingRule]]. self initialize. self addEntry: (Entry new setAccount: aCreditAccount amount: aMoney charged: aTimepointOrDate). self addEntry: (Entry new setAccount: aDebitAccount amount: aMoney negated charged: aTimepointOrDate). creator := aPostingRule. aSetOfEntries do: [:i| self sourcesAdd: i]. self checkInvariant. Object>>require: aBooleanBlock aBooleanBlock value ifFalse: [self error: 'Precondition Violation'] Transaction>>checkInvariant |balance| balance := entries inject: Quantity zero into: [:total :each | total := total + each amount]. self require: [balance = Quantity zero].Look at DBC elements! When I started to use DBC in dynamically typed Matlab it was clear that before checking function parameters value I should check their types (storing type in a variable name like aQuantity for documentation is even worse than Hungarian notation). And here it is, the approach known 6 years ago.
I hope nobody will call setAmount with integer money, cause [false. true.] value equals to true and precondition violation would not be noticed <g>.
Thinking about add and change reminds us about delete. Discussions about feature removal are rare and it may seem hard to do right, but in the light of this musings delete requires only to know how the program works. So delete = change - add. In other words, change = delete one thing and add another (on the other hand, delete often results in change of the other objects interconnections).
To minimize maintenance we can reduce number of change requests (using BDUF) or reduce cost of change (using solid software engineering practices). We can also try to transform change requests into the new feature requests, but following this principle while postpone the maintenance increase cost of change.You may ask what wrong in using good engineering, it certainly can reduce cost of change to the level of new feature addition. But it requires great skills and not everyone want to invest time in education. Unfortunately, I don't see how to avoid it, except of using (fragile and limited) big up front analysis.
How XP recommends to struggle with bad habits? Not. Code test and solution any (dirty) way down. Then recall code quality and refactor. These three steps supposed to be short term pleasant and despite that good in long term too.
You know all this jokes about "test addicted", "XP pusher" sometimes not so funny, for example when code 10 lines long too complex for me to comprehend, when I fear to refactor without tests, when I can't write code without user story and AT. Maybe it's my personal problem and not relevant to XP, but it seems like I'm very bad now in solving complex and abstract problems. Fortunately(?) I successfully simplify my current programming tasks, but type theory, lambda calculus, correctness proof, high level (UML) analysis are too complicated for me. When I read about projects like Sholis or when developers did not compile program for months and result yet has almost zero defects or when requirements thousands pages in size regularly changed and team handles it without claims of using XP I want to know how is it possible, I want to learn this techniques, but I can't.I want to be better developer, not simpler. Though there is a relationship.
From the shrink-wrap user point of view, looking at my programs I think the only product that was buggy enough for me is Win95, it was replaced by Win2000 in February 2000. All other programs were selected by the means such as price, compatibility and features.
From the in-house developer point of view, assuring quality (debugging and manual testing) took much of my time. Maybe it's my another personal problem <g>, but I can't throw raw code to my users. Instead I chose to study software engineering, which also supports program evolution.
Conclusion is surprisingly clear. One needs to be better developer to be more productive. My 2 main projects last 3 and 5 years, so I better be productive in a long run.(Other areas such as drivers, frameworks, languages probably have own peculiarities).
"Since there are often too many parameter combinations to test all possible scenarios, the tester must use some methodology for selecting a few combinations to test" The Combinatorial Design Approach to Automatic Test Generation.
Other essays by Michael Bolton. At least, read Zero Balances and Zero Responsibility, Installation Programs and Effective Beta Testing. No, you can't read only one <g>. Most entertaining is A Review of Error Messages.Duties of an application testing tool
1. Simulate user operations.Low level operations are easiest to implement. Sometimes they have user stories behind, e.g. "status bar should indicate object name under the mouse cursor" or "draw a red circle at the top of a graph".
When application GUI controls are standard OS controls, medium level also achievable. But not all text on the screen represented using controls -- labels and status bar information usually rendered as pixels.Application level control requires special developers work. It can be COM API, command line interface or exclusive extension.
Experience evaluating TestCompleteOne my project is a MSVC++ MFC app, other is in Matlab. All controls are native, so TC successfully drives them. There are extensions that allow to instrument MSVC++ program to be "open" for TC (call internal program functions from an external script), but I don't use them yet.
TC provide functions for screenshots capture, save/load and seek one image inside other (comparing parts of images less brittle to future changes).For test code you can use VBScript, C++ Script or Delphi Script (mini CLR <g>) inside TC. Outside you have access to all TC functions through COM. Special (.h) library allows you to cut'n'paste between C++ Script and real C++, e.g. Sys["ActiveWindow"]["WndCaption"] works equally well in the script and in the language. Very convenient.
Recording facility creates UI commands equivalent to user operations. Plain recording is exactly what makes GUI testings so brittle, but it's a quick start to familiarize yourself with the tool and beginning of the tests development. Help from the tool is the only way to deal with controls without title such as edit boxes, result looks like setEditText(p.inputForm["Window"]("MWEDIT4194304", "1", 9), "1000").VisualWorks applications are special. They don't use native controls, so you must use special tools. SilverMark's Test Mentor seems to be the one and only such a tool. It costs $3500, comparing to $350-$500 for TC. Anyway, evaluation version is always free <g>.
TM comes in parcels and intended to be used in development image. No support for testing deployed application, i.e. you can't test already deployed program and you can't test is everything included in deployed image during runtime packaging (I mean you can't test it automatically, manual testing is always with you)
TM's preferable tests development strategy is through UI recording. For example, you can add empty recording step inside test and TM will execute steps before planned recording (e.g. setup), then it will record your actions and then it will execute steps after recording (e.g. cleanup). So, you don't need to prepare application for recording manually. For verification you should select widget in the window using mouse, then TM will show list of parameters (specific for selected widget) and their current values. Selecting elements in this list automatically creates verification step. You can copy steps and scenarios, instead of recreating all from a scratch. Never before you could create lots of redundant data so easy <g>.Programming tests, main showstopper is that I failed to give UI time for message processing. Obviously, I can't write selectMenu: 'Add'. press: 'OK', because message for menu needs to be processed in UI subsystem -- then dialog with OK button will appear. Adding Processor yield or delayFor: 1000 after selectMenu doesn't help. In TM GUI shell's scenario this two messages form two steps. When TM executes them, it does insert appropriate pause. Unfortunately, I don't know how. Perhaps when running tests TM creates different thread for itself.
Thus, instead of plain old functions I'm stuck with a GUI containing steps with code blocks like
self varNamed: 'newsToAdd' put: (NewsItem fromArray: #(2 'April 1, 2003' 'text')).
CommonSuite runScenarioNamed: 'Add news'
TM practice is to create each assertion in different step. When unit testing, I often create several assertions in one function. Creating different step for each assertion is an additional work, but result more intention revealing. As more people work with AT and some of them may be non-programmers, it seems like a good approach.
GUI of TM itself quite ugly and buggy, while rich for running tests and analysing results. No problems during recording and playing scripts (I successfully reimplemented tests that were made using home-grown library). No descriptions in assertions. Little documentation and absence of discussions on web. All that is typical for VW.
So, it's a working tool. Disadvantages don't matter because there are no alternatives. Flashing windows of working ATs shine, especially if you don't know about lots of duplication ready to blow some day.All my ideas come from experience visiting other news resources. Most convenient scenario is when reader visit news page in exactly the same rate with it's updates (usually daily). If this is the case, news page should contain only new information. My style is different -- I can skip days, I can post several times per day and, most important, it's hard for me to post every day in the same time (but it's a good idea).
When reader visit news page more often than it updates, typical approach is to show her "yesterday news". Reading twice is a duplication that I want to refactor. Thus my Compact News (why almost nobody use it?).
When reader visit news page less often than it updates, typical approach is don't think about this case. Web top posters must die. Anti chronological order in news is like code before test. Thus again my Compact News where order is correct.
There is also first time visitors which interested in archives. Why typical archives are also in anti chronological order???
Here is my design. Main News page contains news for last month (32 days) in most simple (ac) form. Compact News page contains news for last two weeks (15 days). Archive page contains all news since the beginning. Permanent link to Archive is at the bottom of News page.
Perhaps I'll add more features later. Your ideas will be highly appreciated.
Basic idea is that given precondition function obliged to satisfy its postcondition. It makes interfaces very explicit and robust. Client knows what to prepare for function call and what a result will be. Supplier can rely on precondition that simplify its job to single responsibility.
For me DBC is the next big step after TDD (which in turn occurred 1.5 years ago). They have much in common: drive design before code, require some time practicing to comprehend, document code. But while TDD is deductive approach (by example), DBC is inductive (by specification). And as both specification and customer tests required for software product, DBC and TDD both help developer build correct solution.
See also this more detailed introduction to design by contract. But more importantly try it for yourself. Precondition checks are most valuable and don't require anything from the language. Postconditions harder to formulate and often TDD solution more simple.
Two examples which happened last week that I talked about at the beginning.1. For my Matlab project I wrote a function that snaps current mouse coordinates over graphic to data points. This function was thoroughly TDD tested with presumption that graphic's data (signal in time or spectrum) starts from 0. Later we added new type of graphic (autocorrelation function) that spans time interval from -T to T. It took some time to realize that cursor coordinates are now wrong and localize the problem. If I had explicitly written down precondition, I would immediately got error pointing to my (too restricted) function.
2. For my Smalltalk project I wrote a function for substring replacement. Presumption was that source string must contain substring to replace. Then I by mistake (wrong cut'n'past) passed to this function variable news instead of news_xml. Result was an internal VW library assertion and I spend some time to figure out that problem not in my function, but in caller. Again, if I had explicitly written down precondition it would been obvious immediately.
Today I killed the Bug which for two weeks terrorized our development team. Steps to reproduce problem were known and easy to follow (it occurred during program startup), but bug appeared only once in 10 to 20 runs when it knows we were hunting (and once in every 2-3 runs when we tried to work <g>).
As I discovered, the key was in mouse movement. If you move mouse over forming window, mouse move handler facing absence of (not yet created) principal objects wreak havoc. Actually, bug (unexpected axes object) was side effect of query gca command. gca returns current axes object and, if there is no axes yet, it creates one. The and clause is documented behaviour, but obviously I were not aware of it.
Lessons for me:How don't waste your time developing software? Ideal development would be typing all code in a row, then deliver application (or, even better than typing, just say it or draw it to computer). No, it's an ideal programming. Development also includes gathering and analysis of requirements, which in ideal world could just be written down as well.
Requirements simplicity comparing to bloated code comes only from omissions. Large part of requirements is in implicit form (doesn't "Clean up your room" extremely vague?). Using modern programming languages and complete requirements in English, programming is a barely syntax reformatting. And I think requirements is not complete without specification of how things should be done (having requirements/specification document we should be able to run our system in manual mode without computer). Software libraries reuse is exactly the reason for chasm between users/developers and programs. Of course reuse also has a lot of benefits and programming task is to bring it to project.
Debugging is a tool to better understand program. Testing to check our assumptions. Refactoring to evolve program. Modularity to manage complexity (calling lots of H2O molecules "an ocean" is also a modularity). It seems everything is important <g>. But novices do spend much more time on the same tasks comparing to experienced developers. So, difference is only in effectiveness. Time waste as inverse of productivity again has led us to importance of skills.
Software Testing and Internationalization book by Manfred Ratzmann and Clinton De Young is a modern view on (agile) application testing. Most things are familiar, but check out Testing by Documenting ("Does it really work the way I say it does?") and Interactive Unit Tests ("call a single function interactively" when number of test cases "goes into the hundreds").
I'll use this book as a reference to well known practices in which I have some doubts.
1. "Acceptance testing as Black Box tests". Not able to test everything, we must maximize effectiveness of chosen tests and White Box testing could point out important and dangerous boundary conditions. Maintaining tests, we must minimize their number and White Box testing is exactly the tool to remove duplication from tests (if some functionality implemented through common function, we don't need to test this functionality every test case).
White Box AT blurs the line between unit and acceptance testing, improves non developers' understanding of the product and enriches requirements/specification documents. Moving AT closer to developers removes duplication with UT and could be effectively combined with UI and interunit communications testing.
2. "Use a scripting language to produce tests". I use C++. Yes, it's my native language and all that, but rumors about disadvantages of statically typed languages are big exaggeration anyway. If testing is a software development, why shouldn't we use best development practices?
1. Our goal to is maximize business value of the product to customer for minimal cost and time. Code quality more important for development and maintenance (minimize cost and time). Business value is in working and specific requirements.
2. In XP, design, coding and testing are single activity. We can add requirements gathering and acceptance testing, but they still don't overlap - each activity helps in unique way (BTW, this is why we can't do "less XP", but we can do "more than XP").
3. Measuring time spent on each activity is easy, but without 1 and 2 it doesn't matter.
So, PSP is too narrow for me. It talks only about coding (TSP not better) and talks about work harder, not smarter - it doesn't introduce new practices. Well it talks about reviews, but from the paper I don't see what exactly does it mean - who, when and how perform this reviews? I hope it's not as bad as in Keith's and Ron's experience <g>.
PSP also strives for planning accuracy. According to Kari Hoijarvi: "It seems, that I'm probably the only one person in the world that finds both XP and PSP useful ... At least for me, the biggest measurable advantage of PSP is schedule prediction and tracking." I think, if it is important for you, just plan often.Nevertheless, I will try again to measure my time spent. I tried 1.5 years ago: for 1 month I manually recorded all activities. It requires very good reporting facility, I hope I'll create one this time. And I definitely need automatic tool, at least something like Activity Recorder. It's like profiling application - I want to see the hot spots.
But it's not the only source of fun in programming. Human beings have two source of "fun": pleasure and evolution. Evolution through creativity covered in the previous paragraph, the second part of the evolution is learning. Learning new things, there is no learning without new word.
Aren't there lot of new technologies in programming? The more experience I have and the more mature computer science is the more slowly new technologies come to me.Purpose of this reflection was to discover why I'm not so excited in development as most of the programmers (including myself in youth).
I easily give people second chance. It's very rare that there is absolutely no time or resources to correct a mistake. And once I have the final result this is the point to judge.
It's about acknowledging mistakes in public. Not very easy, right? Generally, there are two sources of failure: not enough effort and not enough knowledge. Both are quite unpleasant for the one who expected result from you. But effort and knowledge are not "mistake" as we know it. Mistake by definition is something small: typo, missed event handler, broken cup. Mistake by definition is something fixable. On the other hand, we have car crash or big loss of data witch are called "incompetence". This distinction is only by result, not by human activity.Thus acknowledging mistake isn't important - you will be judged by result. Acknowledging mistake sometimes presumes that you will learn from it. But, even if it true, it's "implementation detail" - there are lot of other ways to learn. Nobody care how you avoid making mistakes - just don't do them and everything will be OK.
Acknowledging mistake might have good psychological effect for the team: you signing to fix it and often free of charge, others looks smarter in contrast to you, you take off the blame from others. Making good things for the team pays back, but don't forget the cost.
Mistakes do have cost. Sometimes negligible, sometimes enormous. Try to control it.Holodeck product by Security Innovation. First of all read Software's Invisible Users by James A. Whittaker (do you remember his "Test aerobics" clip?).
Brilliant ideas! Interactions with OS severely underrated. James also talks about unintended functionality, which particularly dangerous in security applications (Testing for software security, scanned 15 MB article). And it's not only ideas, Holodeck performs all low level work to assist tester in exploring an application.
From the test first developer point if view, Holodeck can be used instead of mocking OS API. Ability to substitute any function in Win32 or .NET API allows unprecedented control over OS memory manager behavior, file access and network connections. For example, using samples and external interface from the trial Holodeck version, I created two small test applications in Managed C++: first denies file access to Notepad (so File Dialog doesn't show any disks, directories or files), second runs my own application limiting memory usage to 30 MB (my program gracefully managed first use case that required lot of memory and terminated on second). According to docs, I can substitute any system call with my own function or just return arbitrary error code. "Permanent" substitution could depend on input function parameters. "Dynamic" substitution might occur during program run, e.g. you can intercept interface just before particular test case.
While Holodeck is not free and first version GUI is not very useful and we yet can't handle more conventional human user interactions very well, this is the way to go. And using Holodeck API (which is always more preferable anyway), you can solve some kind of the problems right now.
Found via Eric Jarvi's blog.It's nice to think about general solution contrary to burdensome application specific trace messages, which cover only a small part of the picture. So, let's think.
Running as non-admin or Developer Lifestyle "...developing code as a non-privileged user and helping start a culture change on the Windows platform" seminal article by Keith Brown.
I always was a big (personal) security fan, reading and using appropriate stuff. And I always ran as a single most privileged user, but not anymore. Additional thanks to Craig Andera for popularizing these ideas.
Well, I'm not trying to sell security here. Rather I'm trying to bring out multi-user and limited privilege scenarios. Scenarios for which you should develop your applications. And, please, consider also scenario when user reinstalls OS and wants to preserve all settings <g>.
Try it one day. This is all-time experience.
It seems to be the best security blog available: joatBlog.
Top discovered link is a masterpiece called Caring for Your Introvert.
Top discovered security link is a Practical Approaches to Recovering Encrypted Digital Evidence. One clarification: quantum cryptography is to prevent eavesdropping at all.
Path: HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\NukeOnDelete
Result: ACCDENIED
Exception Management Architecture Guide. "This document discusses design and implementation guidelines for exception management systems that use .NET technologies. It focuses on the process of handling exceptions within .NET-connected applications in a highly maintainable and supportable manner."
What interesting is the exceptions in distributed applications and logging for maintainability. So, you can skip the basics (try, catch, finally) and start right from a Gathering information.
"TestComplete should be installed and used under the same account and this account should be set to administrator ... Perhaps, the situation will be changed in one of the future versions, but not anytime real soon." Bobby Edgar, AutomatedQA.
I don't want to work as admin and I don't have any alternative to TC. To think about...Found via Brad Wilson's blog.
Rubik's Cube intermediate release 2 is ready in Code section. It even solves sometime.
Besides Eiffel and Direct3D, I learned how not to optimize unrefactored code.Mike Clark presented Continuous Performance Testing With JUnitPerf article recently. I also did performance testing in several projects, I see a room for improvements in this generally unexplored area and I'd like to discuss it.
Simplest approach to optimize good working code is:start = getCurrentTime(); executeHotspot(); elapsed = getCurrentTime() - start; if elapsed > timeAllowed assertEquals(timeAllowed, elapsed);
Problems with profiler:
"... I was convinced that being able to separate what is important from noise was the main task of an engineer, and also that of a physicist. If you take into account all the factors that are involved into a certain real situation then calculations quickly become cumbersome and meaningless. Yes, meaningless, because very big formulas are very good at hiding what is really going on.
... you have to know what to leave out of your model, what to approximate. Maybe latter you will add a little something to the model and your results will get better; but now you already understand what is going on.
... abstraction is the key to being a better engineer. At least for me. Abstraction is a process by which what is important in some situation is separated from what is not important."
Radu Grigore, Notes 0001."As projects increase in sophistication, programmers often need a means to better reuse and customize existing component-based software. To achieve such a high level of code reuse, programmers typically employ a feature called generics. In Whidbey, the CLR will include a type-safe, high-performance, compile time-verified version of generics which differs slightly in syntax and greatly in implementation from templates as found in C++ and generics as proposed for the Java language. Generics allow developers to author, test, and deploy code once and reuse that code for a variety of different data types with negligible performance impact to applications. The CLR implementation of generics will also reduce code bloat when compared to other strongly-typed implementations, leading to more readable and maintainable source. Microsoft currently plans to support both the creation and consumption of generics in C#.
In addition to improving code reuse, Visual C# will eliminate some chaotic chores often associated with coding, such as implementing enumerator patterns. Iterators are constructs that dramatically simplify this task. Based on similar features in research languages such as CLU, Sather, and Icon, these constructs make it easy for types to declare how the foreach statement will iterate over their elements. Rather than having to create the classes and build the state machine for manually implementing the enumerator pattern, the C# compiler will translate iterator code into the appropriate classes automatically.
Anonymous methods are practical language constructs that will allow C# programmers in the Whidbey timeframe to create code blocks that can be encapsulated in a delegate and executed at a later time. They are based on a language concept called a lambda function and are similar to those found in Lisp and Python. Anonymous methods are defined dynamically at the point where they are used, rather then being pre-defined as a named method of a specific class. Anonymous methods make some types of operations more convenient, particularly when the method signature or body needs to be changed at run time."
Visual Studio + C# is already extremely (short term) productive environment. Now C# is moving towards long term projects, while VB.NET stays for simple tasks. Do not underestimate MS Language.Porting my custom wizards from VS 2002, I wrote a tutorial Custom wizards in MS Visual Studio 2003 for C++ projects.
I think it's enough for me to solve Rubik's Cube. Simple 4 steps look ahead + intelligent weight function just doesn't work. And I don't have any interest to implement complex algorithms required .
This experiment helped me a lot to try Eiffel language. I never thought those beautiful constructions are so hard to use. Lack of free functions and even static functions in classes; inconvenient loop with increment in a body, not in a header; embarrassing implementation inheritance, not composition; no enums; slow general functions like deep_clone and is_equal.
Nice features are, of course, native DBC; general functions like deep_clone; general persistence facilities. I have plans to finish OOSC and online future Eiffel book draft, then will come the final opinion.
So far, I've put release candidate executable in Code section. Now program has separate thread for processing, less delay between moves, ability to rotate cube planes from keyboard.
Hierarchies. Top-down decomposition. Divide and conquer. Does it make access to data easier?
Look at MSDN library, what do you use to read about some function? Contents? No, it's index. Look at file system, what do you use to open usual programs or files? File manager, Start menu? No, it's TypeAndRun or desktop/quick launch shortcuts (if it doesn't hurt your aesthetics). Look at writing, what do you use to save a file? File - Save? No, it's Ctrl+S.
The point is that all these intermediate layers are slow and unnatural. Natural way is 1 to 1 mapping (if I want to turn power off, I press Sleep button, I don't go to Start - Shutdown - ...).
How it relates to programming? Well, every programmer knows that most instant access is through global variables <g>. Strive for great names, prefer direct objects collaboration.
Next time you will structure, try to look further.
User Stories Applied for Agile Software Development book draft by Michael W. Cohn. This is work in progress and it covers user stories, requirements, planning, users, acceptance testing, XP and SCRUM. Everything is quite familiar for experienced XP reader. What particularly good in this book is a classification of users and separation of users from customers, managers and other not-a-real-users.
I wish I would find something about agile documentation. Besides the code, I see a need for:
1. Acceptance tests documentation for developers. Tests code is not enough, because:2. User guide for users and developers.
3. Short presentation (overview) for newcomers.
1 and 2 directed to preserve information, while 3 - to transfer it.
Michael also wrote an interesting small article on resource validation Configuration Bugs That Bite. Not that two solutions offered looks very appealing, but the point is to pay attention to this problem.
Programming made easier. Today, without any previous experience, I've wrote windows service, that maintains performance counter representing current HDD temperature. As access to performance counters from VBScript kind of complicated, I've additionally created separate WMI class and finally got it from vbs.
Documentation, frameworks and IDE from MS are programmers' best friends.
I would publish this app, if some settings were not hardcoded for my personal configuration. If anyone has interest, feel free to contact me.
Thinking about Proof vs Test (as in recent discussion in comp.object), sure, good proof guarantees better implementation than good tests, but there are other things that we are interested in software development - primarily design (managed complexity) and system evolution.
As of today, proofs are manual, while tests are automated. That makes tests more preferable for evolving systems. Tests (TDD) also help in design, making it more simple.
Now, what about other practices? What about DBC? DBC clearly is a design technique and automated almost as well as the tests. More interesting is that DBC also facilitates automated proof and simplifies implementation along with the tests.
Looking into the future, I see the needs for more design and more flexibility. Spreading DBC principles now is the right thing to do.
It also has some limitations - an applicability of OO in general, Eiffel in particular and year of publication (1997) in excuse.
All in all I highly recommend to read it.
Now I'm going to finish "Improving Web Application Security: Threats and Countermeasures" . Then I'll read ongoing work on future third edition of "Eiffel: The Language" by Bertrand Meyer. It's available here (username is "Talkitover", password is "etl3").
I've decided to list electronic versions of books in my Reading section. From the past reading I've included "Programming Applications for Microsoft Windows" Fourth Edition by Jeffrey Richter.
"Improving Web Application Security: Threats and Countermeasures" by Meier, Mackman, Vasireddy, Dunner, Escamilla and Murukan. Title is quite misleading, I would call it "Modern Windows Security: The Complete Guide". This book covers everything from TCP/IP to Web Services, from Registry to Isolated Storage, from ASP.NET to SQL Server, from code review to deployment. It uses theory (assets, vulnerabilities, threats, attacks and countermeasures) and practice (code examples, checklists, tools).
Why my current work doesn't have anything with security? <g> For those like me, I can recommend to read about code access security in .NET (security relations between assemblies) and DPAPI (W2K encryption API that uses the user's logon credential).
I've restricted my reading plans in Reading to a bare minimum and added my first XP book "XP Installed" to recommended part.
I found rubik solver in Amzi! Prolog + Logic Server samples. Core engine was written in Prolog by Dennis Merritt, but this product offers interfaces to other (modern) languages. So, my project got a new hope to be useful.
Release candidate 2 (see Code section) is now finally able to solve the cube, more fast and less memory hungry. The only thing left is the code cleanup. I'm also interesting how it works on the other computers - your feedback is welcome.
I'm also using NUnit 2.1 now, but there are hardly any useful features for me comparing to 2.0.
My Cube demo drops 300 frames for 60 seconds run at 100 fps. I thought it was .NET garbage collection.
There is a great tool CLR Profiler that you can read about and download from these 2 articles: Writing Faster Managed Code: Know What Things Cost by Jan Gray and Writing High-Performance Managed Applications : A Primer by Gregor Noriskin. It allows you to see life of every object in your application and it fast. When, for example, AQTime slows my demo by a factor of 10, CLR Profiler runs it almost in real-time.
CLR Profiler distributed in source code and you have to build it for yourself. I recommend to change its temporary directory from %WINDIR%\TEMP to something more appropriate (e.g. %TEMP%) and fix 2 bugs in ReadNewLog.cs (it fails when loading large logs with IndexOutOfBounds error).
You should run CLRProfiler.exe under Admin account. I recommend to turn off Calls tracing, otherwise log file size will be very large and processing will be slow. Most interesting analysis view is Time Line, which shows heap and work of garbage collector.
Well, GC is bad for applications like my demo. It could run anytime, stopping all other threads in (simple) application for 10 - 50 ms (1 - 5 frames). The only way to "control" it is System.GC class with Collect method, which doesn't even guarantee to compact heap (the most time consuming operation in GC cycle). But as GC runs only once in 5 seconds and compacts heap only once in 20 seconds (according to CLR Profiler) it can't drop more then 30 frames.
The real problem with performance turned out to be dependant on window size. With window of 400*400 pixels I had 300 frames dropped, increasing it to 600*600 I got 500 dropped frames. It doesn't depend on rendered scene complexity, so I think it's just raw video/memory/bus speed when copying frame buffers. I made a little tweak changing SwapEffect from Discard to Flip (it reduced drop count in large resolutions for 20%-50%).
Finally, I reduced default window size to 300*300 (100 dropped frames in 60 s) and considered it done.
BTW, a one way to measure frame rate in DirectX applications is Fraps utility. Although, Trace.WriteLine + DebugView is a way more flexible <g>.
When you Add Reference to your C# application in VS IDE, components in main list is not from the GAC. E.g. you may have DirectX 9 runtime installed and Managed DirectX libraries in the GAC, but you would not see it in VS.
To workaround this problem you can add key like this one to the registry:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\DirectX] @="F:\\WINDOWS\\Microsoft.NET\\Managed DirectX"(you can point to any directory and use any key name AssemblyFolders\My Key).
Then copy your dll files (like Microsoft.DirectX.DirectSound.dll) to this directory.
Reading on XP brings me less and less new information and I decided to stop. There are lot of other topics to master. My current interests are .NET, security, Eiffel and C++. I also very interested in functional languages and formal program verification, but I plan to study it later.
I feel myself obliged to update Links section.Refactoring, Extreme Programming and Test Driven Development are gone from my Yahoo! Groups. comp.soft-sys.matlab is gone from my Newsgroups - my Matlab project successfully finished 3 month ago.
Dale H. Emery added to Weblogs. Psychology is also one of my interest. The only reason I didn't link to Dale earlier - is that I though everybody knows about his page anyway.
Craig Andera, Raymond Chen, Brad Wilson, Chris Sells and Roy Osherove are added to .NET/Windows Weblogs. I posted links to them, so you should have your own opinion already.
Added to Security Weblogs: joatBlog - you know him, A Day In The Life Of An Information Security Officer - great investigation stories, two .NET security blogs by Ivan Medvedev and Greg Fee.
Management Weblogs section consists of two blogs by Johanna Rothman and one by Esther Derby
Two Yahoo! Groups added: Windows Technical: Off Topic - unofficial discussions in great company, Eiffel Software User list - Eiffel developers list.
3 lists from discuss.develop.com on .NET: ADVANCED-DOTNET, DOTNET-CLR and DOTNET-CX. I didn't try appropriate .NET newsgroups, but I think that signal/noise level in these lists is a way more better.
Two newsgroups added: comp.lang.eiffel and comp.software.testing (recent testing tools news).
Some blogs that I read, but didn't link: Martin Fowler's Bliki - it doesn't match my interests. Michael Feathers, Ron Jeffries and Christian Sepulveda started their blogs, but don't post much. And I recently discovered Pete Kruckenberg's Perfect World.
I don't read Troy Jessup's Security Blog, but it's the most beautiful one that I've seen.
// Generics: Stack<int> stack = new Stack<int>;
// Constrained genericity: public class Dictionary<KeyType, ValType> where KeyType : IComparable
// Implementation of iterator interface for class developers: public class ThreeElementsList { public string foreach() { yield "microsoft"; yield "corporation"; yield "developer division"; } } public class List { internal object[] elements; public object foreach() { foreach(object o in elements) { yield o; } } }
// Anonymous methods: public class MyForm { ListBox listBox; TextBox textBox; Button button; public MyForm() { listBox = new ListBox(...); textBox = new TextBox(...); button = new Button(...); button.Click += new EventHandler(sender, e) { listBox.Items.Add(textBox.Text); }; } }See also little discussion on this document and Design and Implementation of Generics for the .NET Common Language Runtime paper by Andrew Kennedy and Don Syme.
It's not as powerful as .NET CAS, but certainly useful.
function_call(value1, value2)You can also set eif-body-comment-indent to 1 (default is 0) to shift comments off the code.
It's a great complement to OOSC. OOSC concentrates on design, while this book concentrates on programming. So, read first OOSC and then this book.
As it's a language reference, it's not always very entertaining. Parts of the book are still not finished and last update was 1 year ago. But you just have no other choice. You, as general Eiffel developer, can't get this information from other sources. And it's still has quality of Bertrand Meyer's work.
I am more comfortable with Eiffel now. When I've been reading OOSC it was mostly what I can't do in Eiffel, but ETL3 shows that Eiffel is quite practical and contemporary. Eiffel was one of the first languages with support of .NET and Eiffel Software still actively develop new tools and environments, offering free editions as well.
While Eiffel community is extremely small and Eiffel job market behaves accordingly, the language is quite unique/capable to justify its study. Meanwhile, I have 3 more weeks to finish and send my Cube demo to Eiffel Class Struggle 2003.
I recently received latest Bruce Schneier's book "Beyond fear" and Harry Beckwith's "Selling the invisible". It will be my current reading for now.
I tried to use VMware 4.0.5 to tests my Cube demo compatibility with Windows 2000 and 2003. Direct3D did not work under emulation. I mean, W2K virtual machine + DirectX 9.0b retail (redistributable) runtime + Managed DirectX demo + Reference DeviceType = Can't create Direct3D device.
It's not new. The news is that when I installed DirectX SDK Summer update on virtual machine it began to work. You don't have to install full SDK, Install DirectX Runtime + Install Additional Runtime Debug Files is enough.
Then I tried the same trick with the original (old) DirectX SDK and yes, it also works.
Cube demo v1.00 binaries (1 MB). It still requires .NET 1.1 and DirectX 9. New features: fullscreen mode, wireframe mode, cube maintains proportions when changing window size, option for black background, option for software rendering.
Source code will be released later.Jeffrey Richter's "Applied Microsoft .NET Framework Programming". Assemblies, reference and value types, constants, properties, events, enumerated types, attributes, delegates, exceptions, memory management, reflection, fundamental patterns (convertibility, equality, cloning, disposing).
This book focuses on IL level and also describes how many of C# language constructs maps to IL code. It's very useful for non C# developers.
No threads, no interoperability with unmanaged code, no remoting. Written style is good, but nothing special.
Overall, book is good. It's my first CLR book and I've learned a lot.
.NET lost several points in my eyes - lack of good design is obviously clear. Programming in C# without generics and multiple (implementation) inheritance requires to write a lot of duplicate code. Things will be better in Whidbey (C# 2.0), but then we will also have revisited MC++ (see also Ecma International Moves to Standardize C++ Binding for CLI) and, probably, Eiffel Envision 3.0 <g>.
Bruce Schneier's "Beyond fear". Security trade-offs, examples, analysis, statistics.
If you read Bruce, you will admire this new book. He doesn't repeat himself and writing is excellent.
If you don't know Schneier and security, well, each of his books is a right place to start.
Harry Beckwith's "Selling the invisible". Service marketing.
Services are different from products (we don't use them often, they are more hard to evaluate, we can make most of them yourself).
While focusing on marketing, the first thing this book suggest is to improve your service. Then it talks about naming, pricing and other visible things which make image of service in prospect mind.
The book is very small and reminds me "UML distilled" - lots of practical and smart suggestions, touching broad topics (all very relevant) and staying in focus, citing examples and other books.
Software development is service, especially when you use XP model. That was the reason I bought this book. But it gave me more - broader view on not obvious (but important) market aspects.
"Peopleware" (Second Edition) by Tom DeMarco and Timothy Lister.
Book for managers, not for me.
One of my favorite tools, CLR Profiler (memory usage profiler for .NET applications) was updated recently (10/28/2003).
New in version 1.1:Nicolai Josuttis's "The C++ Standard Library". Utilities, containers, iterators, functors, algorithms, strings, I/O, internationalization, allocators.
Excellent balance between tutorial and reference, readability is very hight. Code examples for almost everything. Library internals revealed to facilitate understanding. Hard answers to practical questions included (components thread safety, errors in standard, typical standard implementation that you can rely on).
Some parts of the library were of less interest to me (I/O, alocators, numerics), but without this book I would not know what I don't use. German accent is noticeable and a little disturbing (for me, non native English reader).
It considered to be the best book on the subject. I concur.
I'm ready to design my own file manager.
Here it is - SurF. It's not a product (I've worked on it for only 3 days), but a statement.
Herb Sutter's "Exceptional C++".
First of all, it's not just a reprint of C++ Guru of the Week - it's a new (very readable) book.
For such a complex language as C++, books like this one is an excellent opportunity to refresh (and correct <g>) your knowledge.
Good article on very interesting for me subject.
Found via Darrell Norton's blog.Overeaters Anonymous: Exceptions, Part II by Marc Miller (nice weblog, BTW).
I'll give you my example.
Test:
Allows to create directory.
Go to Temp directory in Surf.Code:
void FileListView::keyDownHandler(System::Object* sender, WinForms::KeyEventArgs* e){ if (e->KeyCode == WinForms::Keys::F7){ NewDirectoryDialog* dialog = new NewDirectoryDialog(); if (dialog->ShowDialog() == WinForms::DialogResult::OK){ System::String* dir = System::IO::Path::Combine(directory->FullName, dialog->directory()); makeDirectory(StringToWStd(dir)); changeDirectory(dir); } } } void makeDirectory(const std::wstring& dir){ System::IO::Directory::CreateDirectory(dir.c_str()); }
Now, let's focus on makeDirectory. First of all, sometimes it will not be able to create directory (because of wrong name or read-only device) and it's not exceptional scenario. So, I better change its name to tryMakeDirectory. To see how exactly CreateDirectory could fail let's look at MSDN:
.NET Framework Class Library
Directory.CreateDirectory Method
Creates all directories and subdirectories as specified by path.
Parameters path The directory path to create.
Return Value A DirectoryInfo as specified by path.
ExceptionsException Type | Condition |
---|---|
IOException | The directory specified by path is read-only or is not empty. |
UnauthorizedAccessException | The caller does not have the required permission. |
ArgumentException | path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars. |
ArgumentNullException | path is a null reference. |
PathTooLongException | The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters. |
DirectoryNotFoundException | The specified path is invalid, such as being on an unmapped drive. |
NotSupportedException | Creating a directory with only the colon (:) character was attempted. |
These are two type of exceptions: invalid argument exceptions and IO exceptions. Minimally designed system should make arguments requirements explicit, but with .NET we should devise it ourselves. And there is the third exceptions type: CLR exceptions (like System.StackOverflowException, System.OutOfMemoryException, System.ExecutionEngineException) which could occur any time.
Following (my) good practices I should ensure function arguments requirements (eliminating ArgumentException, ArgumentNullException, PathTooLongException, NotSupportedException), catch and process IO exceptions, let CLR exceptions go through up to the call stack.
How I can "ensure function arguments requirements"? There is no ValidatePath. If I try to create it from "Condition" statements, then documentation to Path.InvalidPathChars says: "This array is not guaranteed to contain the complete set of characters that are invalid in file and directory names." Bad luck.My current code is:
bool FileListView::tryMakeDirectory(const std::wstring& dir){ //REQUIRE(valid_characters(dir)); bool result = false; System::String* error; try{ System::IO::Directory::CreateDirectory(dir.c_str()); result = true; } catch(System::IO::IOException* e){ error = e->Message; } catch(System::UnauthorizedAccessException* e){ error = e->Message; } catch(System::NotSupportedException* e){ error = e->Message; } if (!result) WinForms::MessageBox::Show(error, (L"[Surf] Error creating " + dir + L" directory").c_str(), WinForms::MessageBoxButtons::OK, WinForms::MessageBoxIcon::Warning); return result; }
Explanation. PathTooLongException and DirectoryNotFoundException inherit from IOException. ArgumentException "should not be possible" as I use PathCombibe to make dir. ArgumentNullException is not possible as I pass non NULL.
But having said all that I'll probably go back to Win32API for this use-case (boost::filesystem doesn't support wide strings, yet).
Root of the problem, of course, is not in exceptions. It's just CreateDirectory should not throw anything: it should assert path validity and return error code for runtime IO problems.
BTW, Eiffel .NET developers have even more fun missing(?) direct catch filters. Code looks like:
feature try_make_directory(dir: STRING): BOOLEAN is local exception_occured: BOOLEAN error: STRING do if not exception_occured then feature {SYSTEM_DIRECTORY}.create_directory(dir) Result := True else show_error_message(error) end rescue if last_exception_type.is_equal("System.UnauthorizedAccessException") then exception_occured := True error := tag_name retry end end feature last_exception_type: STRING is local e: EXCEPTION do e := feature {EXCEPTION_MANAGER}.last_exception if e /= Void then Result := e.get_type.full_name else Result := "" end ensure Result /= Void end
Code is clear and stable now. NUnit doesn't work with MC++ assemblies and I didn't find a solution for it. So, I don't have a single unit test yet. It's quite interesting experiment to develop without UT. Although, this program has almost zero logic. Of course, I have lots of acceptance tests. And I use DBC. Assertions without doubt change my design, I don't think unit tests would change it the same way. Without UT I have to run program more often for manual testing, this is bad. But again, for GUI and API interactions UT doesn't fit well anyway.
Ever wondered at System.Drawing.Color names? How are Beige, BurlyWood, Linen look like?
Color Names page will show you.This release doesn't properly indicates missed cube resources.dll, hiding mouse cursor works awfully with dialogs, debug build doesn't indicate not installed DirectX and debug build has serious issues with HIGH_RESOLUTION_TIMER. But if you just watch the demo (as a good user <g>) you shouldn't care about it.
Concerning HIGH_RESOLUTION_TIMER. I use QueryPerformanceCounter Win32 API function directly from Eiffel now (previous versions used it via intermediate C# library). And I have a small example which (maybe not deterministically, but 100% reliably) reproduces memory corruption in Debug build (can't reproduce for Release build). Eiffel Software has no answer why it happens and whether it is the problem with Eiffel compiler or not. If it wasn't just a demo I would revert back to C# library.Probably it's a little early to talk about my experience in Envision 2.0, but I can't leave my article in Envision 1.2 state.
So, what I found most useful in 2.0:
1. Name overloading.
You can write create {VECTOR_3}.make(x, y, 0) now instead of
create {VECTOR_3}.make_from_value_x_and_value_y_and_value_z(x, y, 0).
2. Lots of (small, but nasty) bugs fixed.
You can read more about improvements here (it is Eiffel Studio online documentation). Not news, but other useful link is External features, also missed in Envision docs.
Not all is fixed in v2.0 unfortunately:
1. I had problems with installation and References browsing doesn't work on my non-admin account. But on other machine with Windows 2003 it works fine for casual User.All in all, it is a step forward. Envision team gives us free version of the real Product for .NET development in Eiffel. They are extremely responsive on (our) user feedback and just need a little more time.
Herb Sutter's "More Exceptional C++".
I like it even more than the first book. While first book sometimes goes to dark corners of C++, this book is practical from the first page to appendices. It is also 64 pages longer :)Scott Meyers's "Effective STL".
You can't read to much about C++. Scott brings out a lot of STL usage/performance details and explains them extremely well.The "Empty Tab Bug" unveiled:
__gc class FileListView{ FileListView(){ new System::Threading::Timer(new System::Threading::TimerCallback(this, timer_handler), this, 1000, 1000); } void timer_handler(System::Object*){ Invoke(new TimerDelegate(this, on_timer_in_UI_thread)); } void on_timer_in_UI_thread(){ REQUIRE(!InvokeRequired); if (fileWatcher->any_changes() && tabManager->is_tab_selected(parentTab)){ BeginUpdate(); Items->Clear(); std::vector<FilePath> entries = directory_contents(current); for (std::vector<FilePath>::const_iterator i = entries.begin(); i != entries.end(); ++i){ FilePath fullFileName = path_combine(current, *i); add_list_item(i->cli(), file_icon(fullFileName, BackColor), file_color(fullFileName)); } EndUpdate(); } } }; System::Drawing::Color file_color(const FilePath& file){ System::Drawing::Color result = System::Drawing::Color::Black; System::IO::FileAttributes a = System::IO::File::GetAttributes(file.cli()); if (a != -1){ if (a & System::IO::FileAttributes::Hidden) result = System::Drawing::Color::DarkGray; else if (a & System::IO::FileAttributes::Encrypted) result = System::Drawing::Color::Green; else if (a & System::IO::FileAttributes::Compressed) result = System::Drawing::Color::Blue; } ENSURE(result == System::Drawing::Color::Black || result == System::Drawing::Color::DarkGray || result == System::Drawing::Color::Blue || result == System::Drawing::Color::Green); return result; }As timer fires from separate thread, we need to marshal this call to UI thread (via Invoke) and only from UI we actually perform list update. InvokeRequired helps us do not forget about it.
The question is "Why list sometimes stops to display any contents while everything else works fine?".
The answer is "Because GetAttributes throws when it can't find the file". Why I don't handle it? Because MSDN says:File.GetAttributes Method Return Value The FileAttributes of the file on the path, or -1 if the path or file is not found.OK, it throws, but why "everything else works fine"? Where is this exception gone? Exception goes from file_color to on_timer_in_UI_thread to Invoke and finally to timer_handler. Remember, timer_handler is in separate from UI thread. So, exception silently kills timer thread and "everything else works fine". While without EndUpdate list doesn't display anything anymore.
The lessons are:
"... it is usually relatively straightforward to create a header file named std.hpp that includes all the standard headers:
#include <iostream> #include <string> #include <vector> #include <deque> #include <list>This file can then be precompiled, and every program file that makes use of the standard library can then simply be started as follows: #include "std.hpp"
Normally this would take a while to compile, but given a system with sufficient memory, the precompiled header scheme allows it to be processed significantly faster than almost any single standard header would require without precompilation. The standard headers are particularly convenient in this way because they rarely change, and hence the precompiled header for our std.hpp file can be built once.
Some committee members find the concept of a comprehensive std.hpp header so convenient that they have suggested introducing it as a standard header. We would then be able to write #include <std>. Some even suggest that it should be implicitly included so that all the standard library facilities become available without #include."Never before I heard about this approach (to precompile standard headers) from a distinguished C++ experts like David and Nico. And yes, it makes total sense. I immediately made three files for SurF: std.h, boost.h and platform.h (Windows and .NET stuff). All plus dbc.h included in stdafx.h.
It significantly reduced #include clutter in .cpp file headers. (Total rebuild time was also reduced from 30s to 21s).I also, finally, added strings like #using <System.Windows.Forms.dll> to platform.h. It was necessary for VC++ 7.0, but 7.1 doesn't require it anymore. I added them to enhance Visual Assist intellisense capabilities, that turns out still depend on #using includes.
"Thank you for participating in the beta test program for Eiffel ENViSioN! 2.0 ... We also would like to announce that Sergey Vlasov is the winner of the beta-test program. He reported the highest number of high quality bug reports. As such he will receive a free copy of Eiffel ENViSioN! 2.0."
There is a lot of power inside this box."C++ Templates: The Complete Guide" by David Vandevoorde and Nicolai Josuttis.
The title of the book ("... we found a dearth of literature that concentrates on the fundamental concepts and advanced techniques of [templates]") and authors (distinguished C++ experts) make any additional recommendations to read unnecessary. It's all about argument deduction, specializations, instantiations, names look up, metaprogramming, etc, etc.But even more valuable is an application of these rules. Descriptions for Barton-Nackman trick, empty base class optimization, curiously recurring template pattern, expression templates, SFINAE principle. Lots of examples and future directions of C++ language.
What an indispensable book for modern C++ development."Pattern Hatching" by John Vlissides.
Patterns usage and development by example. I don't see patterns usage to be challenging and patterns development to be actual for me.On the good side, this book describes Generation Gap pattern that recommends encapsulate automatically generated code (by GUI wizards, script preprocessors) in separate class and provide handwritten behavior in class that inherits from it. I think this is the right thing to do (although I can't evaluate it as I don't use wizards).
Overall, this book was not of much value for me.Another colors reference (now in alphabetical order, better for search and offline storage): C# Color Name Table by Joseph Newcomer.
See also his Win32 to .NET map: C# for MFC programmers Quick Equivalents Map.Working software today and tomorrow
slogan is added to the front page."Windows Forms Programming in C#" by Chris Sells.
Forms, dialogs, drawing, printing, controls, design-time integration, resources, data binding, multithreading, web deployment, serialization. "Parts of this book have explored sections of the framework that are completely outside the System.Windows.Forms namespace because you need that knowledge to build real WinForms applications."
"... this book does a great job of hitting a huge number of features". It was great for me as a second book on .NET (after Richter's on CLR fundamentals). Such (pure technology) overviews are very useful for starters. But if you are experienced .NET developer or reader (Chris wrote lots available online and in MSDN), this book would be a less valuable.
A Shareware Life blog by Thomas Warfield. Shareware business model, marketing, games development. One more way to make money.
Found via Dana Epp's (security) blog.SurF version 0.25:
Learning from mistakes: the Don Quixote pattern story by Roy Osherove. "... no initial time estimation was expected of me. After the couple of days were over I went to my team leader and said that I am still investigating the various ways in which this would be possible to do."
It is so easy to create environment where having a problem is only your problem. Where it is so desperate for you to get stuck. This is the scenario I afraid most from a new job, and unfortunately it is real.It is so easy to create environment where that couldn't happen. Where you work in pairs. Where business objectives don't allow you to spike for more than a day or two. Where you can leave the problem to your subconsciousness and return to it later.
It is not very easy to make the right choice, to not make a mistake."The Common Language Infrastructure Annotated Standard" by James S. Miller and Susann Ragsdale.
I expected to learn IL code and better understand .NET principles. Unfortunately:It's important for application developers not to concentrate on (MS) technology too much. So, I recommend to look for a more concise source on the topic.
Static Verification and Extreme Programming paper by Peter Amey and Roderick Chapman from SPARK team.
Reminds us that automatic code analysis is possible, if we write contracts and have verifiable coding standard."Managed DirectX 9 Kick Start: Graphics and Game Programming" by Tom Miller. Lots of Direct3D from points to vertex and pixel shaders, sound, input devices, 2D graphics, networking, audio and video playback.
Tom is the development lead for MDX and blogger. In this not a very big book he touched plenty of topics. Most of the book contents are comments to enclosed examples. Examples are very illustrative and essential for such a complex API as DirectX.
On the dark side, this book is small enough to go in depth. Has as a target audience intermediate level programmers - comments are often excessive. Code quality is not high - code duplication particularly bad in printed form.
Overall, it's a best MDX overview book so far. Very interesting for hobbyists. For 3D specialists it's perhaps too simple. Non-game developers probably should wait for a more mature 3D API.
I started from GRAPE library, but didn't find analog for Win32 FloodFill function (one of my figures is filled triangle and I don't know how to draw it other than drawing three lines and then filling the interior). So, I turned to WEL library and got the work done. I needed only the picture, but I've got also a standalone executable that I can distribute to others.
One thing that I were particularly interested to know is how external resources (such as Win32 pens and brushes) are freed in Eiffel (how it can work without RAII <g>). To my surprise it works automagically in GRAPE - I can create any number of pens without a single GDI leak. In WEL I have to explicitly call delete.
That's all with Visual Eiffel for now.Paul Graham's "On Lisp". "This book is intended for anyone who wants to become a better Lisp programmer". Perhaps I should have took this description more seriously when I looked for a general introduction to functional programming. I had carefully read two first chapters of "ANSI Common Lisp" (also available online here), first 5 chapters of "On Lisp" and then skimmed through the rest of the book. Lisp language is very simple and "untyped" (just like Smalltalk) while I like to have help from compiler and "typed" intentions, so I didn't have an incentive to go deeper.
Overall, most material was familiar for me from modern C++ approaches like templates meta programming. Except nondeterminism, that I encountered adapting Rubik's Cube solver written in Prolog.
I will try to read "Developing Applications With Objective Caml" by Emmanuel Chailloux, Pascal Manoury, Bruno Pagano. OCaml language seems more practical and proper for me.I'm in a process of changing my organization. I don't work for NII RES anymore and I'm going to stop my software development activities at Mechel.
So, I don't program much these days.A Comparative Study of Language Support for Generic Programming paper by Ronald Garcia, Jaakko Jarvi, Andrew Lumsdaine, Jeremy Siek, Jeremiah Willcock.
"This paper reports on a comprehensive comparison of generics in six programming languages: C++, Standard ML, Haskell, Eiffel, Java (with its proposed generics extension), and Generic C#. By implementing a substantial example in each of these languages, we identify eight language features that support this broader view of generic programming."Eiffel ENViSioN! version 2.01 was released on March 25, 2004. I haven't tried it yet.
Proposal to add Design by Contract to C++ by Thorsten Ottosen from C++ Standards Committee Post-Sydney mailing.
Updated Links.
Web: Comeau C-C++ Online conformance test was removed (I don't use it, VS 2003 is (good) enough for me), Agile Articles and Hedgehog Archive were removed as these sites don't work anymore.
Newsgroups: comp.object's description was altered (formal methods advocated by Costin Cozianu and Steven Perryman even more appealing for me now than "classical agile" point of view); comp.std.c++ was added for discussions on C++ future; microsoft.public.dotnet.framework.clr, microsoft.public.dotnet.framework.drawing, microsoft.public.dotnet.framework.performance were added for my interest in .NET essentials; microsoft.public.win32.programmer.directx.managed was added for my interest in Managed DirectX.
Blogs updated in Links.
Updated links to Dale H. Emery, Raymond Chen, SecurityMonkey, Ivan Medvedev. Added link to short (blog only) joat.
Removed links to Keith Ray (trying to minimize agile reading) and Greg Fee (not supported anymore).
Added links:
General section: Ars Technica - tech news, Lambda the Ultimate - computer science, Pete Kruckenberg - networking the world, Charles Cook - computing, Darrell Norton - agile .NET, Gunnar Kudrjavets - quality software, Valery Pryamikov - different and same.
Security section: Dana Epp - developing secure software, Michael Howard - MS security.
.NET (old Windows) section: Mike Gunderloy - critical news, Joel Pobar - Rotor, Rico Mariani - on performance, Tom Miller - Managed DirectX, Fabrice Marguerie - tools and source.
Employment (old Management) section: Zoe and Gretchen - careers at MS.
Testing section: Jonathan Kohl - tester and developer collaboration, Tim Van Tongeren - testing real world.
Mail lists updated in Links.
Updated links to Boost and Eiffel Software User list.
Added SecurityFocus Mailing Lists: BugTraq - reading since October 2000, Focus on Microsoft, Firewalls, Secure Programming.
Added NTBugtraq - "discussion of security exploits and security bugs in Windows NT, Windows 2000, and Windows XP plus related applications".
Added DOTNET-WINFORMS list from discuss.develop.com.
Added discuss.microsoft.com lists: DirectX programming issues and Compiler Developers for .NET
Added Resistance as a Resource Yahoo! Group - Dale Emery's list.
For the last 7 months I'm working as Information Security Administrator at Mechel Chelyabinsk. My main responsibility is a protection of users workstations - about 2000 Windows computers, mostly connected to local network:
I always have interest in security and now on this job I've got hands on experience and deeper understanding. I better realize how vulnerable we are now and how much improvements required for software to become secure.
I'm also missing my software development activities and I'm looking for opportunity to get back.I'm using TopCoder currently to rebuild my C++ skills and get trained on quick algorithmic solutions - it's great! Practice rooms have all tasks from previous competitions and each task has solid description and extensive test suit.
Today I participated in live competition (Single Round Match 226, Division 2) as GliderTC. Solved easiest task of three. And solved second (medium) a minute after coding phase had finished :( I have no idea how people solve all 3 tasks in these 75 minutes. Maybe I should use shorter variable names <g>.
It's refreshing to write in pure C++ without Boost, .NET libraries and Windows API. Programming is fun again!Unusual Scanner version 0.20 - disk scanner for nonstandard (possibly malicious) files (readme). I wrote it for my current work to simplify analysis of client computers infected with trojans. I also wrote server part - it checks file for known malware using Kaspersky Antivirus engine and databases. I implemented very simple and unreliable file transfer protocol between client and server, so I don't distribute server part with uns publicly.
Experimental Rubik's Cube version 1.28 with DirectX 9.0c support. Expect stable version in a week.
Experimental SurF version 0.43. Expect stable version in a month.
Rubik's Cube version 1.30 with DirectX 9.0c support (readme). If you already saw previous version (1.20) no need to download this one.
Previous versions of Rubik's Cube was developed for the very first version of DirectX 9 (v1.0900). DirectX 9.0c was released a year ago and it includes only v1.2902 components. And then DirectX 9.0c June 2005 edition includes only v1.2906 components. Overall, end user has hard time to use applications dependent on old Managed DirectX components. This version of Rubik's Cube supports DirectX 9.0c Gold and DirectX 9.0c June 2005 edition (and it will probably fail under newer...).
This version of Rubik's Cube was compiled using Eiffel Envision 2.5 (previous version used v2.0). While Eiffel Envision 2.5 still doesn't work under non-admin account out of the box, it is fixable by coping HKCU\Software\Classes registry keys from Administrator account to HKCU\Software\Classes in User account. (Actually, it took me a week to make it work on 2 different computers, but I can't reproduce what special I did for that).
Proudly presenting SurF File Manager version 0.48. There are large improvements over previous v0.26 and you can read about it here.
I've also simplified Code page removing my old projects and shortening thoughts on code importance."C++ Coding Standards" book by Herb Sutter and Andrei Alexandrescu. Reference of best practices in modern C++ development. The authoritative book that can officially support your personal coding style <g>. Discusses what needs to be discussed - concise and practical.
This is how C++ Coding Standard in your organization should look like.Updated resume and foto.
I'm actively using COM (ActiveX, BHO, RPC) in my current project - never used it seriously before.
So, I reread Dale Rogerson's "Inside COM" - why COM interfaces and how they differ from C++ interfaces, registry, aggregation, marshalling. All fundamentals and ideas of COM. Good book.Finished reading George Shepherd's and Brad King's "Inside ATL" (I was very interested in libraries that simplify COM usage). The book describes ATL wizards and classes. For me, it's too shallow for reference and too detailed for practical guide. My current objects work fine from ATL wizard's code and I don't ask for more.
I've started reading Don Box's "Essential COM"...I hope this is all I need to know about COM.
1. std::vector<System::Byte> doesn't compile now. Changed it to std::vector<unsigned char>.
2. Delegate creationDoubleClick += new System::EventHandler(this, double_click_handler);had to be changed to
DoubleClick += new System::EventHandler(this, &BaseFileListView::double_click_handler);3. I use ui_strings.resx and ui_strings.ru.resx files for English and Russian interfaces. In VS 2003 Resource File Names were:
$(IntDir)/$(RootNamespace).$(SafeParentName).resources $(IntDir)/$(RootNamespace).$(SafeParentName).ru.resourcesI accessed them using
resources = new System::Resources::ResourceManager(S"SurF.ResourceFiles", System::Reflection::Assembly::GetExecutingAssembly());In VS 2005 I got a System.Resources.MissingManifestResourceException and had to change Resource File Names to:
$(IntDir)\$(RootNamespace).$(InputName).resourcesNow I access them using
resources = new System::Resources::ResourceManager(S"SurF.ui_strings", System::Reflection::Assembly::GetExecutingAssembly());
4. System::Windows::Forms::ListView lost file colors in a very bizarre way. First, it shows files with black color. If I resize window - all colors appear normal. Until I select file - then it becomes black again. My solution was to add WinForms::Application::EnableVisualStyles() call to main.
5. I obtain file icons in separate thread using:void ColorIconUpdater::start(){ workerThread = new System::Threading::Thread(new System::Threading::ThreadStart(this, work)); workerThread->Start(); } void ColorIconUpdater::work(){ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); SHGetFileInfo(file, 0, &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_SMALLICON); CoUninitialize(); }In VS 2005 this CoInitialize fails with RPC_E_CHANGED_MODE and I changed it to:
void ColorIconUpdater::start(){ workerThread = new System::Threading::Thread(new System::Threading::ThreadStart(this, &ColorIconUpdater::work)); workerThread->SetApartmentState(System::Threading::ApartmentState::STA); workerThread->Start(); } void ColorIconUpdater::work(){ SHGetFileInfo(file, 0, &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_SMALLICON); }6. System::Net::Dns::GetHostByAddress is marked as obsolete in VS 2005, but
GetHostEntry("192.168.67.1").HostName == "192.168.67.1"; GetHostByAddress("192.168.67.1").HostName == "SV";I'll continue to use GetHostByAddress.
7. Label.AutoSize = true doesn't change actual size immediately anymore. Changed it to:
label->AutoSize = true; label->Size = label->PreferredSize;
1. [System::STAThreadAttribute] now works for WinMain and I happily removed previous unreliable workaround:
System::Threading::Thread::CurrentThread->ApartmentState = System::Threading::ApartmentState::STA;as first line inside WinMain.
2. Added DoubleBuffered = true; for ListView that implements file list. No more flickering!
3. System::Drawing::Icon slightly changed scale code and I finally noticed that my up and current icons were scaled from original 16*16 to 32*32 when loading from resources and then back to 16*16. So, I changed LoadIcon to LoadImage and problem solved.2. Build time is 10-20 % slower in VS 2005. SurF.exe build by VS 2005 runs all tests 8% faster in Release and 100% slower in Debug builds.
void BaseFileListView::WndProc(WinForms::Message* m){ bool menu_msg = (m->Msg == WM_INITMENUPOPUP || m->Msg == WM_MEASUREITEM || m->Msg == WM_DRAWITEM) && *shell_menu; WinForms::ListView::WndProc(m); if (menu_msg) (*shell_menu)->HandleMenuMsg(m->Msg, m->WParam.ToInt32(), m->LParam.ToInt32()); }In .NET 2.0 when I selected Send To submenu SurF terminated with FatalExecutionEngineError in WinForms::ListView::WndProc call. I changed this function to:
if (menu_msg) (*shell_menu)->HandleMenuMsg(m->Msg, m->WParam.ToInt32(), m->LParam.ToInt32()); else WinForms::ListView::WndProc(m);Works fine now.
I developed following template to correctly use autoscaling:
WinForms::Button* connect_as = new WinForms::Button(); Controls->Add(connect_as); ClientSize = System::Drawing::Size(400, 200); AutoScaleDimensions = System::Drawing::SizeF(6, 13); AutoScaleMode = WinForms::AutoScaleMode::Font; connect_as->AutoSize = true; connect_as->Text = S"Connect as..."; connect_as->Location = System::Drawing::Point(10, 10); connect_as->Click += new System::EventHandler(this, &SelectShareDialog::on_connect_as);
Bug, feature? Where to report?
Unfortunately, it doesn't work. I managed to apply Rename, Replace Literal and Extract Method to empty native Win32 project, but nothing more complex - inclusion of <iostream> breaks SlickEdit, using SlickEdit on C++/CLI project fails, Move Method refactoring fails.
Back to the manual coding again...It's possible to create malformed data file that will lead to access violation when loaded using CArchive MFC class (Bug Details).
Martyn Lovell's response: "Thanks for the report. This is the kind of situation we should be robust to. We'll try to fix this in time for our service pack."And you can't copy comctl32.dll from XP to 2000 as it depends on other XP system components (like kernel32.dll).
Once I developed for Managed DirectX without SDK using only Runtime Components and I thought maybe it will work for Avalon too. I installed WinFX November CTP Runtime Components - entire package is 43 MB, web install for my system is 16 MB. Tried Chris Sells examples and found that I can't change XAML even for C# without SDK.
But maybe I don't need XAML? I like to write my UI in C++ anyway. I tried to access Avalon directly and it seems to work. Documented it in my new article Avalon without XAML.Highly recommended.
I'm a strong believer in multi-paradigm programming. Wish to have time to write something big in Prolog and Haskel...
My conclusion is that "Exceptional C++ Style" adds little value to Sutter's previous excellent work.
It's modern look at Authentication and Authorization technologies on Windows platform and beyond. WCF, InfoCard and why we need unifying identity metasystem.
Happy reading!I converted SurF from Managed C++ to C++/CLI last week. Conversion was rather straightforward and if I knew it is so easy I'd made it earlier. 80 percents of conversion is to convert * to ^ and new to gcnew for .NET classes. Do use regular expressions for it (but take into account that Replace in Files with Regular expressions eats last symbol in tag for closed files, so Keep modified files open after Replace All).
For example, to convert * to ^ for classes from System namespace use:Find what - System\:\:{[a-zA-Z\:]+}\* Replace with - System\:\:\1^
It will replace System::Exception* with System::Exception^ and so on.
To convert new to gcnew use:Find what - new System\:\:{[a-zA-Z\:]+} Replace with - gcnew System\:\:\1
Everything else could be found in C++/CLI Language Specification. Language overview clause is particularly informative.
My big personal problem was that I used same Name (SurF) in application manifest as name of exe file (SurF.exe). I knew that manifest file name should be different from exe name and named it appropriately, the problem is that during ClickOnce installation manifest file name is changed according to Name in application manifest (becoming SurF.exe.manifest)! With this foreign manifest my exe was not able to use built in manifest and "failed to start because MSVCP80.dll was not found". Now that I know about it this is not an issue any more.
Using mage.exe it is possible to automate manifests generation from command line. I generate application manifest almost completely automatically (manual is only version number) using following line:mage.exe -New Application -FromDirectory surf -Processor x86 -Name "SurF File Manager" -Version 0.55.0.0 -ToFile surf\SurF_File_Manager.manifest -CertHash "01 df 59 30 ef 11 84 6b 55 ca 90 55 ba f5 93 be 07 a2 27 23"
Deployment manifest is significantly less automatable from command line, so I generated one using mageui.exe and use mage.exe to update it for new builds:mage.exe -Update surf\SurF_File_Manager.application -AppManifest surf\SurF_File_Manager.manifest -CertHash "01 df 59 30 ef 11 84 6b 55 ca 90 55 ba f5 93 be 07 a2 27 23"
It's nice to have Web installer! (current prerelease version is here .NET 2.0 required).When I wanted to add custom application icon to ClickOnce installer for SurF and mage.exe didn't have command line switch for it that was the last straw. I moved to MSBuild.
Now I have one deploy.proj file:<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <DeployUrl>use property parameter</DeployUrl> <SupportUrl>use property parameter</SupportUrl> <Version>use property parameter</Version> <Description>use property parameter</Description> <UpdateInterval>use property parameter</UpdateInterval> <UpdateUnit>use property parameter</UpdateUnit> <Thumbprint>01 df 59 30 ef 11 84 6b 55 ca 90 55 ba f5 93 be 07 a2 27 23</Thumbprint> </PropertyGroup> <ItemGroup> <EntryPoint Include="SurF.exe"/> <IconFile Include="app.ico"/> <Dependency Include="ru\SurF.resources.dll"> <AssemblyType>Managed</AssemblyType> <DependencyType>Install</DependencyType> </Dependency> <File Include="doc\*.*"> </File> <File Include="settings\*.*"> </File> </ItemGroup> <Target Name="Build"> <GenerateApplicationManifest AssemblyName="SurF_File_Manager.exe" AssemblyVersion="$(Version)" Dependencies="@(Dependency)" Description="$(Description)" EntryPoint="@(EntryPoint)" Files="@(File)" IconFile="@(IconFile)" OutputManifest="SurF_File_Manager.manifest"> <Output ItemName="ApplicationManifest" TaskParameter="OutputManifest"/> </GenerateApplicationManifest> <SignFile CertificateThumbprint="$(Thumbprint)" SigningTarget="@(ApplicationManifest)"/> <GenerateDeploymentManifest AssemblyName="SurF_File_Manager" AssemblyVersion="$(Version)" DeploymentUrl="$(DeployUrl)" Description="$(Description)" EntryPoint="SurF_File_Manager.manifest" Install="true" OutputManifest="SurF_File_Manager.application" Product="$(Description)" Publisher="Sergey Vlasov" SupportUrl="$(SupportUrl)" UpdateEnabled="true" UpdateInterval="$(UpdateInterval)" UpdateMode="Background" UpdateUnit="$(UpdateUnit)"> <Output ItemName="DeployManifest" TaskParameter="OutputManifest"/> </GenerateDeploymentManifest> <SignFile CertificateThumbprint="$(Thumbprint)" SigningTarget="@(DeployManifest)"/> </Target> </Project>Following command line executes it:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" surf\deploy.proj /property:Version=0.56.0.0 /property:DeployUrl=http://surf.svprogramming.net/install/SurF_File_Manager.application /property:SupportUrl=http://surf.svprogramming.net "/property:Description=SurF File Manager" /property:UpdateInterval=6 /property:UpdateUnit=DaysResults of build are signed application and deployment manifests (with custom application icon that is shown during installation and in Start menu). For C++ projects which VS2005 doesn't support with Publish IDE feature this approach is far more powerful and maintainable comparing to Mage and MageUI.
Speaking about app icon, actually you can set it in MageUI: select icon file in application manifest and double click on File Type cell.
I planned to include deployment manifest in SurF zip archive to enable local ClickOnce installer and updates in addition to web installer and updates. Unfortunately, this scenario is not supported as application identity for ClickOnce application includes the URL where the application file originally came from. It means that if you install application from local path and then try to update it from web site you lose application settings - same application that is deployed from different URLs is two different applications from ClickOnce point of view.
I ended up with separate ClickOnce web installer and xcopy zip archive.Lock-based programs can't provide any of the above guarantees. If any thread is delayed while holding a lock to a mutex, progress cannot be made by threads that wait for the same mutex; and in the general case, locked algorithms are prey to deadlock."
Introductory articles for lock free programming:"Leading at the edge: leadership lessons from the extraordinary saga of Shackleton's Antarctic expedition" by Dennis N. T. Perkins presents analysis of Shackleton's expedition accompanied with case studies of modern business leaders facing significant organizational challenges.
"I believe that Shackleton and others who have faced the limits of human endurance have left an invaluable legacy. This legacy incorporates the leadership strategies outlined in this book, but it extends beyond that. The lessons drawn from the experience of others can help individuals to clarify their personal values and to make decisions about the kind of people they want to be as leaders. By defining ourselves, we will be better able to reach The Edge - wherever and whenever we choose to pursue it."It clarified a lot for me.
Producing Open Source Software: How to Run a Successful Free Software Project book by Karl Fogel. While I do use and write free software I never actually learned about it. What makes many developers and users contribute to project? How to organize and attract them? Why OSS projects distributed and licensed the way they do? It's all in the book.
"More than 61% of our survey respondents said that their participation in the focal F/OSS project was their most creative experience or was equally as creative as their most creative experience" (Why Hackers Do What They Do: Understanding Motivation and Effort in Free/Open Source Software Projects by Karim R. Lakhani and Robert G Wolf). Count me in.Lazy evaluation, Declarative Computation Model, Declarative Concurrency, Message-Passing Concurrency, Transactions, Relational Programming, Logic Programming, Distributed Programming, Constraint Programming. I wish I'd read it much, much earlier. Not now when I'm so immersed in C++. Not now when I'd read it only as programming concepts overview without delving in the details, without idea how I can try it in practice.
Draft version available for download here.BTW, there is also Ease At Work presentation on Google Video. It has nothing with the book, but everything with Kent Beck.
MPL in itself doesn't resonate with me. The reason is probably it's more suited for library developers and I'm more focused on application programming right now. So, I can't say I've taken much from this book personally. Strong writing nevertheless.
On the one hand given logical problem was easily solved by traditional OO and functional means, on the other hand applying LP you don't have to solve it at all! I will definitely try to stretch declarativeness further in my work.
Speaking of Test Complete, I'm not completely happy with it either and plan to try Ranorex.
I would say this is exactly the amount of information open source developer should know about licenses in exactly understandable language. Excellent book.
Made little benchmark of VS 2008 C++ parallel build performance today.
Hardware: Intel Core2 Quad (Q6600) @ 2.4 GHz, 3.5 GB RAM.
Soft: Windows XP 32bit, Visual Studio Team System 2008 + Feature Pack.
Solution: Native C++, boost, std, std::tr1.
Tested varying maximum number of parallel project builds (PPB) and /MP compiler switch making full solution rebuild:
PPB = 1 + /MP Disabled | PPB = 4 + /MP Disabled | PPB = 1 + /MP Enabled | PPB = 4 + /MP Enabled | |
Project1 CPU time, s | 1 | 0 | 1 | 1 |
Project2 CPU time, s | 20 | 21 | 9 | 9 |
Project3 CPU time, s | 3 | 3 | 3 | 7 |
Project4 CPU time, s | 14 | 15 | 10 | 11 |
Project5 CPU time, s | 5 | 6 | 4 | 7 |
Total CPU time, s | 43 | 45 | 27 | 35 |
Total clock time, s | 46 | 36 | 29 | 22 |
So, 4 cores give me 46/22 = 2.1 times performance boost.
See also short and entertaining Crypto Blunders online paper by Steve Burnett.
System::Uri^ uri = gcnew System::Uri("pack://application:,,/image.png"); System::Windows::Media::Imaging::BitmapImage^ bitmap = gcnew System::Windows::Media::Imaging::BitmapImage(uri);
I'm gradually watching PDC 2008 videos. (Note that high-quality WMVs include video of the speakers.) Most interesting ideas so far:
Support for my beloved DBC. But it seems only in managed code.
It's always a risk that code change inadvertently significantly increase build time or decrease application performance. These changes are hard to track automatically as slow time variations are completely normal. Visual Studio 2010 TFS displays 10 last build times after each build on a little graph and it is easy to assess it visually. Adding similar graph for UT run time should allow to monitor application performance as well.
"Debugging applications for Microsoft .NET and Microsoft Windows" by John Robbins. I try to avoid debugging making source code as high quality as possible using unit tests, design by contract assertions, exception specifications and code review. And so is John! There is a whole chapter right at a start of the book about assertions, tracing, comments and unit testing.
Most of the book is about development and debugging in Visual Studio .NET. When Visual Studio is not enough John describes other tools (WinDBG, Dr. Watson) and writes (C++ source code included) his own utilities and libraries (CrashFinder, Tester, CrashHandler, DeadlockDetection, MemDumperValidator, MemStress and FastTrace). The book was written in 2003 and analyses mostly unmanaged code involving good amounts of assembler. It's too low level for me right now. I still hope that I don't need such kind of techniques to find bugs in my programs.John is certainly a Windows debugging guru and excellent writer. He wrote a newer "Debugging Microsoft .NET 2.0 Applications" book and maintains an interesting blog. |
Oslo is interesting. For my needs it can replace XML and SQL with a higher level "M" language.
"Four" by "Led Zeppelin" is awesome! "Back in Black" by "AC/DC" is so so. "Bad" by "Michael Jackson" is terrible. |
module Microsoft.Samples { import Language; language MusicLibraryLanguage { syntax Main = s:Statement+ => MusicLibrary(valuesof(s){l... syntax Statement = al:Grammar.TextLiteral "by" ar:Gramar.TextLiteral "is" r... => { Album {al}, Artist {ar}, Rating {r} } token Rating1 = "terrible" | "awful"; token Rating2 = "so so"; token Rating3 = "awesome"; syntax Rating = Rating1 => 1 | Rating2 => 2 | Rating3 => 3; interleave skippable = Base.Whitespace } } |
Module ModuleName { MusicLibrary { { Album = "Four", Artist = "Led Zeppelin", Rating = 3 }, { Album = "Back in Black", Artist = "AC/DC", Rating = 2 } { Album = "Bad", Artist = "Michael Jackson", Rating = 1 } } } |
It's not first grammar parser in the world, but it can be the best. Having rich infrastructure (integration with Visual Studio, syntax highlighting, debugging, visual and programmatic parse errors reporting) and exporting data to different formats (text, XML, databases and programming APIs).
Another example is database table definition using "M". Type Friendship is automatically transformed in SQL table Friendships behind the scenes. Later type Friendship2 adds LoveIndex field maintaining compatibility with older clients. |
More details on .NET contracts:
There are two static contracts verifications tools available: cccheck and Pex. Particularly useful as normal unit tests can't check for precondition violations.
I wandered how library solution allows writing Ensures statement at the beginning of a function and execute at the end. The answer is ccrewrite tool as post build step.Contracts and Pex are available today for VS2008 with an academic license (Non-Commercial Use Only).
CHESS - an elegant solution for finding concurrency bugs in native and managed code.
class Account { int balance; CRITICAL_SECTION cs; public: Account(int b) { balance = b; InitializeCriticalSection(&cs); } int read() { int r; EnterCriticalSection(&cs); r = balance; LeaveCriticalSection(&cs); return r; } void deposit(int n) { EnterCriticalSection(&cs); balance = balance + n; LeaveCriticalSection(&cs); } void withdraw(int n) { int r = read(); EnterCriticalSection(&cs); balance = r - n; LeaveCriticalSection(&cs); } }; |
DWORD WINAPI WithdrawThread(LPVOID param) { Account* a = (Account*)param; a->withdraw(2); return 0; } void RunTest() { Account* a = new Account(10); HANDLE hThread = CreateThread(NULL, 0, WithdrawThread, a); a->deposit(1); WaitForSingleObject(hThread, INFINITE); ASSERT_EQUALS(9, a->read()); } |
Class Account has a bug in withdraw method. RunTest function can theoretically reveal it, but very unlikely in practice. CHESS, on the other hand, systematically and predictably tries different possible thread interleaving and on fourth attempt finds the bug and the problematic interleaving sequence.
"Applications = Code + Markup: A Guide to the Microsoft Windows Presentation Foundation" by Charles Petzold. Describes all WPF elements - controls, drawing primitives, XAML, dependency properties, routed input events, resources, data binding and animation. The book shows no wizards or other helper tools, only C# code and XAML markup - my respect to the author. Writing style is methodological, sometimes even pedantic.
Looks like a reasonable book for the first time WPF learners.namespace boost { struct thread::dummy {}; }
SHFILEINFO shfi; DWORD_PTR success = SHGetFileInfo(L"", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);Under Windows 7 beta it incorrectly returns 5 instead of 1 in shfi.iIcon. A workaround is to provide some dummy path:
DWORD_PTR success = SHGetFileInfo(L"dummy path", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
The book and the library are written first of all with performance in mind - lots of pointers, tasks joggling and complex algorithms. For me correctness and simplicity is more important. Fortunately TBB has really good abstractions like atomics, parallel algorithms, scalable memory allocators and the book provides decent information on how to get started.
This is the only readable documentation on TBB, so if you use TBB you should read this book.I started from making my tests runner parallel aware. In SurF project I have 58 test suits that run after each successful build and take 11.7 seconds (each suit contains 5-20 tests). I also have 4 additional heavy test suits than I run infrequently. All 62 suits run in 25.5 seconds. Using tbb::parallel_for over test suits I reduced normal tests time to 7.25 seconds (1.6x speedup) and all tests time to 9.4 seconds (2.7x speedup) on my quad-core Q6600. Running VS 2008 TS's profiler I see that most time is spend in system CLR modules and I have no idea what I can optimize to get closer to 4x speedup. Maybe I can organize individual tests into separate tasks, but it looks like a lot of work with no guarantee of noticeable speedup.
My second task was QuickPath search speedup. Serial version took 40 seconds to calculate score for each directory on disk. I applied tbb::parallel_for over directories and time grew up to 55 seconds. Uh-oh. Profiler showed lot of time spending in memory allocation. I added tbb::scalable_allocator parameter to two most used temporary vectors and time fell down to 12 seconds (3.3x speedup) - good enough for me.I also used tbb::concurrent_vector - good for concurrent reading and adding elements, unfortunately there is still need for a lock obtaining begin and end iterators when another thread uses push_pack. tbb::atomic<bool> - used it for checking should_stop flag in running thread. I didn't use tasks explicitly and there is no equivalent to Asynchronous Agents in TBB.
Overall, high level threading libraries is a way to go. TBB is available for 2.5 years now - don't miss it.Instead of it, I moved all time measurement code out of TextTransitionsModel and left it to ITextTransitionsView implementation.
class TextTransitionsModel { public: TextTransitionsModel(ITextTransitionsView& view); void on_search_text_changed(); void on_search_completed(); void on_path_updated( const boost::optional<std::wstring>& path); void on_fade_timer_tick(); void on_search_text_changed_timer_tick(); }; |
class ITextTransitionsView { public: virtual void text_box_append_text( const std::wstring& text) = 0; virtual void text_box_clear_text() = 0; virtual void text_box_font_set_bold() = 0; virtual void text_box_fore_color_set_fade() = 0; virtual void search_text_changed_timer_start() = 0; virtual void search_text_changed_timer_stop() = 0; virtual void search_text_changed_time_set_to_now() = 0; virtual void fade_timer_start_time_set_to_now() = 0; virtual void fade_timer_start() = 0; virtual void fade_timer_stop() = 0; virtual bool is_fade_time_elapsed() = 0; virtual bool is_search_text_changed_time_elapsed() = 0; }; |
TextTransitionsModel receives updates on search text changed, search completed, path updated and timers' ticks. It doesn't know anything about real time, but it can start/stop fade and search text changed timers. It can ask the view to store current time - time_set_to_now. And it can ask the view is allotted time elapsed - time_elapsed. Plus the model controls the Full path text, font and color.
Tests for TextTransitionsModel are now very simple using private TextTransitionsView implementation:class TextTransitionsView : public ITextTransitionsView { public: TextTransitionsView() : text_box_font_bold(false), fade_time_elapsed(false), fade_timer_enabled(false) {} virtual void text_box_append_text(const std::wstring& text) { text_box_text += text; } virtual void text_box_font_set_bold() { text_box_font_bold = true; } virtual void fade_timer_start_time_set_to_now() {} virtual void fade_timer_start() { fade_timer_enabled = true; } virtual void fade_timer_stop() { fade_timer_enabled = false; } virtual bool is_fade_time_elapsed() { return fade_time_elapsed; } public: bool fade_time_elapsed, text_box_font_bold, fade_timer_enabled; std::wstring text_box_text; };
void test_bold_font(TestErrors& errors) { { TestErrors::AutoPrefix ap(errors, L"set text and completed"); TextTransitionsView view; TextTransitionsModel model(view); model.on_path_updated(std::wstring(L"1")); model.on_search_completed(); errors.assert(view.text_box_font_bold, L"bold"); } { TestErrors::AutoPrefix ap(errors, L"completed during fade"); TextTransitionsView view; TextTransitionsModel model(view); model.on_path_updated(std::wstring(L"1")); model.on_path_updated(std::wstring(L"2")); model.on_search_completed(); errors.assert(view.fade_timer_enabled, L"timer"); if (view.fade_timer_enabled) { view.fade_time_elapsed = true; model.on_fade_timer_tick(); } errors.assert(view.text_box_font_bold, L"bold"); } }I'm not afraid to test timers code any more :)
1. I used Windows Media Encoder capturing screen of a specific window in high quality. Silverlight doesn't support Windows Media Video 9 Screen codec, so I used Windows Media Video 9 codec in Quality VBR mode. Captured window's width and height should be divisible by 2 or you get "The specified stream does not exist" error.
2. I created Silverlight Application with a test page in Visual Studio 2008 SP1 with Silverlight Tools installed. Modified width and height in Page.xaml to match my video size. Added column for Play button. Added my video with auto play turned off. Added Play button:<UserControl x:Class="QuickPathDemo.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="526" Height="134"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="476"></ColumnDefinition> <ColumnDefinition Width="50"></ColumnDefinition> </Grid.ColumnDefinitions> <MediaElement x:Name="Video" Width="476" Height="134" AutoPlay="false" Source="QuickPathDemo.wmv"/> <Button Content=" Play " Name="bntClick" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" Grid.Column="1"> </Button> </Grid> </UserControl>Added Play button click handler to Page.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e) { this.Video.Stop(); this.Video.Play(); }3. I put QuickPathDemo.wmv from step 1 and QuickPathDemo.xap from step 2 to the images folder on my site. Added reference to QuickPathDemo.xap Silverlight application to the news.html page on my site:
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="526" height="134"> <param name="source" value="images/QuickPathDemo.xap"> <param name="minRuntimeVersion" value="2.0.31005.0"> <param name="autoUpgrade" value="true"> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"> </a> </object>QuickPathDemo.xap and QuickPathDemo.wmv files are loaded with the news.html page load, but with 5 KB and 138 KB in size it is not a problem. Works in FireFox as well as in IE when Silverlight runtime is installed.
Free alpha is available for download. Expect v1.0 release in a month.
Most revolutionizing idea for me is that batch processing (produce 500 tons of steel, then produce 500 car body frames, then paint all body frames, than assembly all cars) is a big waste of resources. Continuous production (produce steel for one car, then produce body frame, then paint, then assemble and sell it) is faster and more efficient. Batch processing is more optimal in single operations, but overall process efficiency (value for customer) is low. Continuous production is also superior in quality comparing to batches.
The book contains lots and lots of examples of lean transformations, for example in Porsche and Pratt & Whitney. These examples don't refine basic ideas much, but are an easy read and create aura of lean inevitability.System.IServiceProvider serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider( dte2_object as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); IMyGlobalService service = serviceProvider.GetService(typeof(SMyGlobalService)) as IMyGlobalService;See How to get services from the VS DTE original blog post that presented this idea.
Roughly speaking, a process (e.g. car wheel manufacturing) could be "stable" or "not stable". "Stable" process can be gradually fine tuned to be as precise as needed (variations in wheel diameter from one manufactured wheel to another can be reduced to be as low as needed). In "unstable" process you can't guarantee to your customer that wheel diameter is in certain limits and to fix it you need to find a variability reason outside the process (e.g. operator need eyeglasses or manufacturing machine requires oil change).
This book explains the foundations of Shewhart's control charts - very practical and industry accepted tool. Statistically processing several wheel diameter measurements you can build Shewhart's control chart that will tell you whether your manufacturing process stable or not. The book also explains why gradually reducing variation in stable process (e.g. up to 1 mm) is economically valuable even when customer accepts wider variation (e.g. up to 5 mm).
Statistical process control works better for continuous variables (diameter, weight) than for discrete attributes (number of bugs, number of failed tests). When final results are new versions of the same program I have even more difficulties to see applicability of SPC. Nevertheless, I do believe that ability to detect unknown errors distinguishing them from natural variability is a very important one. Very well written and principal book for me.I think this book is a nice middle ground between practical WiX documentation and fundamental MSI SDK documentation.
Through the series of thoughtful experiments and introspective writing you will learn a lot about human behavior in everyday life. It resembles Cialdini's "Influence: Science and Practice", but carefully crafted experiments set this book on the next level. Highly recommended.
See also the Predictably Irrational web site.I've started learning about design. Highly recommended guide.
Writing is very good and despite my extensive experience working with Visual Studio I did learn new things.
Very good book that structured my WPF knowledge.
Very interesting analysis, incorporating lots of data from Google, eBay, iTunes, Netflix, Amazon and blogs.
After reading this book I've redesigned my Tabs Studio site. I changed DOCTYPE from HTML 4.01 Transitional to XHTML 1.0 Strict, created fixed width layout with borders and floated some images. Implementing new design required some additional googling, but ideas from the book created solid foundation for my work.
Excellent writing, but I'm not sure in what category to put it - business or psychology.
Too high level for that I already know and too social for my personality to act on. At the very end of the book there are six pages of "Tips from the Trenches for Startups" that was probably more valuable for me than the rest of the book.
Copyright 2008 - 2024 Vlasov Studio (Best in class Visual Studio extensions and tools)