
Those folks did not even bother to take a look at the auto-generated slides before giving their talk, they just went along - absolutely priceless!


Windows platforms may be troublesome to maintain, but most civilian sysadmins simply wouldn't believe the resources the navy can throw at problems. A present-day Type 42 destroyer carries at least four people who have absolutely nothing else to do but care for the ship's command system. As of just a few years ago, this was still a pair of antique 24-bit, 1MHz machines each with about 25KB of RAM.
There may also be perfectly valid criticisms to be made regarding Windows usability. When triggering missile decoys with seconds to spare, one doesn't need a superfluous pop-up box saying "Do you want to use soft kill?" with "Confirm" and "Cancel" buttons. But this kind of thing isn't going to faze you if you're used to entering instruction sets such as "PE L5414.10N L00335.67E R6000 TMDA [INJECT]" from memory without backspace or delete. During combat, mind. The one group of users to whom Windows 2000 might look pretty marvellous are RN warfare operators.
Also, the industry keeps complaining about a labor shortage, while employees complain about a job shortage. I finally got to the bottom of this. Industry is finding a shortage of good people, whereas crappy people can’t get jobs. Universities, with dropping enrollment in engineering programs, are lowering standards so that more people can train to be engineers. Poor engineers enter the job market, can't get jobs, and when they do, they lower the overall pay range. As a result, good people see low wages and a job shortage, and go into other fields, increasing the problem.
Great coders do not fit in typical organizational hierarchies. Because the hierarchy rarely recognizes the value produced by higher quality developers until they are gone.
I've been in this market for over 20 years. What I noticed is that in 90% of the cases, the manager has no clue who is good and who's mediocre. Mostly, he criteria is based on how each one advertise himself.
The difference between programmers, doctors and lawyers is that if a doctor or a lawyer is mediocre you will notice it pretty soon. With the programmers, only time will show the truth.
Excellent piece of writing today from Jeff Atwood, who poses the question how on earth the majority of applicants for a programming job can't even solve the most basic tasks, let's say implement a linked list, or a simple SQL join. Yeah I know there is java.util.LinkedList, but guess what, I have seen people iterating over a LinkedList in a counting loop using get(int index) on each element. Can you say O(N2)? That's just my point! That's why sites like The Daily WTF never run short of stories on "curious perversions in information technology".
So I openly admit that just like Jeff I am getting increasingly tired of being affiliated with a profession where let's say


mscorwks!GetCompileInfo0:000> .load clr10\sos0:000> kb
00 0012d3d0 79216288 0162652c 00166c8c 00000001 mscorwks!gc_heap::mark_object_simple+0x77 (FPO: [Non-Fpo])
01 0012d44c 79213753 79211d81 00000000 00000000 mscorwks!gc_heap::mark_through_cards_for_segments+0x28f (FPO: [Non-Fpo])
02 0012d478 7921248e 00000001 00000000 00000000 mscorwks!gc_heap::mark_phase+0xb6 (FPO: [Non-Fpo])
03 0012d4d4 7921301a 00000000 00000000 00000000 mscorwks!gc_heap::gc1+0x96 (FPO: [Non-Fpo])
04 0012d514 79213c37 00000000 00000000 00000000 mscorwks!gc_heap::garbage_collect+0x1bf (FPO: [Non-Fpo])
05 0012d534 79214e83 00000000 00000000 00000044 mscorwks!GCHeap::GarbageCollectGeneration+0x11b (FPO: [Non-Fpo])
06 0012d564 792d176b 793df808 00000044 00000000 mscorwks!gc_heap::allocate_more_space+0x13a (FPO: [Non-Fpo])
07 0012d788 791b3af0 00000044 00000002 0012d7b8 mscorwks!GCHeap::Alloc+0x77 (FPO: [Non-Fpo])
08 0012d798 791d6280 00000044 00000000 00040000 mscorwks!Alloc+0x3a (FPO: [Non-Fpo])0:000> !verifyheap
VerifyHeap will only produce output if there are errors in the heap
object cbad00: bad member 162652c at 00cbad30
curr_object : 0xcbad00 size = 0
Last good object: 0xcbac940:000> !do 0xcbac94
Name: System.Data.SqlClient.SqlCommand| Rank | Platform | Execution Time (for several thousand valid solutions) |
| 1. | C++ (MSVC) | 250ms |
| 2. | C# (.NET 2.0) with NGEN | 375ms |
| 3. | C# (.NET 1.1) with NGEN | 390ms |
| 4. | C# (.NET 2.0) | 406ms |
| 5. | Java (Java 6) | 422ms |
| 6. | Java (Java 5 Update 10) | 657ms |
| 7. | Java (Java 1.4.2) | 680ms |
| 8. | C# (.NET 1.1) | 790ms |
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Config" nillable="true" type="Configuration" />
<xs:complexType name="Configuration">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="ConnectionString" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="DatabaseType" type="ConfigDatabaseType" />
<xs:element minOccurs="0" maxOccurs="1" name="LogSql" type="xs:boolean" />
<xs:element minOccurs="0" maxOccurs="1" name="Statements" type="ArrayOfConfigStatement" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="ConfigDatabaseType">
<xs:restriction base="xs:string">
<xs:enumeration value="Undefined" />
<xs:enumeration value="SQLServer" />
<xs:enumeration value="Oracle" />
<xs:enumeration value="OLEDB" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ArrayOfConfigStatement">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Statement" nillable="true" type="ConfigStatement" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ConfigStatement">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="ID" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="StatementType" type="ConfigStatementType" />
<xs:element minOccurs="0" maxOccurs="1" name="Code" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Parameters" type="ArrayOfConfigParameter" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="ConfigStatementType">
<xs:restriction base="xs:string">
<xs:enumeration value="Undefined" />
<xs:enumeration value="Text" />
<xs:enumeration value="StoredProcedure" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ArrayOfConfigParameter">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Parameter" nillable="true" type="ConfigParameter" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ConfigParameter">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="Type" type="ConfigParameterType" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="ConfigParameterType">
<xs:restriction base="xs:string">
<xs:enumeration value="Undefined" />
<xs:enumeration value="Byte" />
<xs:enumeration value="Int16" />
<xs:enumeration value="Int32" />
<xs:enumeration value="Int64" />
<xs:enumeration value="Double" />
<xs:enumeration value="Boolean" />
<xs:enumeration value="DateTime" />
<xs:enumeration value="String" />
<xs:enumeration value="Guid" />
<xs:enumeration value="Decimal" />
<xs:enumeration value="ByteArray" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!-- if this is a visual studio embedded resource, recompile project on each change -->
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DatabaseType>SQLServer</DatabaseType>
<LogSql>true</LogSql>
<!-- Oracle: <DatabaseType>Oracle</DatabaseType> -->
<!-- OLEDB: <DatabaseType>OLEDB</DatabaseType> -->
<Statements>
<Statement>
<StatementType>StoredProcedure</StatementType>
<ID>CustOrderHist</ID>
<Code>
<![CDATA[CustOrderHist]]>
</Code>
<Parameters>
<Parameter>
<Name>customerid</Name>
<Type>String</Type>
</Parameter>
</Parameters>
</Statement>
<Statement>
<StatementType>Text</StatementType>
<ID>CustomersByCityAndMinOrderCount</ID>
<Code><![CDATA[
select *
from customers
where city = @city and
(select count(*) from orders
where orders.customerid = customers.customerid) >=
@minordercount
]]></Code>
<!-- Oracle:
<Code><![CDATA[
select *
from customers
where city = :city and
(select count(*) from orders where orders.customerid =
customers.customerid) >= :minordercount
]]></Code>
-->
<!-- OLEDB:
<Code><![CDATA[
select *
from customers
where city = ? and
(select count(*) from orders where orders.customerid =
customers.customerid) >= ?
]]></Code>
-->
<Parameters>
<Parameter>
<Name>city</Name>
<Type>String</Type>
</Parameter>
<Parameter>
<Name>minordercount</Name>
<Type>Int32</Type>
</Parameter>
</Parameters>
</Statement>
<Statement>
<StatementType>Text</StatementType>
<ID>CustomerCount</ID>
<Code>
<![CDATA[
select count(*)
from customers
]]>
</Code>
<Parameters>
</Parameters>
</Statement>
<Statement>
<StatementType>Text</StatementType>
<ID>DeleteTestCustomers</ID>
<Code>
<![CDATA[
delete
from customers
where companyname like 'Test%'
]]>
</Code>
<Parameters>
</Parameters>
</Statement>
</Statements>
</Config>
Assembly.GetExecutingAssembly().GetManifestResourceStream(
"VanillaTest.config.xml"),
"Data Source=(local);Initial Catalog=Northwind;
Integrated Security=True");
IDBAccessor accessor = VanillaFactory.CreateDBAccessor(config);
public interface IDBAccessor {
IDbCommand CreateCommand(CommandParameter param);
IDbConnection CreateConnection();
IDbDataAdapter CreateDataAdapter();
void Fill(FillParameter param);
int Update(UpdateParameter param);
int ExecuteNonQuery(NonQueryParameter param);
object ExecuteScalar(ScalarParameter param);
void ExecuteTransaction(TransactionTaskList list);
}
NorthwindDataset northwindDataset = new NorthwindDataset();
accessor.Fill(new FillParameter(
northwindDataset.Customers,
new Statement("CustomersByCityAndMinOrderCount"),
new ParameterList(
new Parameter("city", "London"),
new Parameter("minordercount", 2)))
);
northwindDataset.Customers.Clear();
accessor.Fill(new FillParameter(northwindDataset.Customers));
northwindDataset.Customers.Clear();
accessor.Fill(new FillParameter(northwindDataset.Customers));
foreach (NorthwindDataset.CustomersRow cust1 in
northwindDataset.Customers) {
cust1.City = "New York";
}
UpdateParameter upd1 =
new UpdateParameter(northwindDataset.Customers);
upd1.RefreshAfterUpdate = true;
upd1.Locking = UpdateParameter.LockingType.Optimistic;
accessor.Update(upd1);
Datatable table3 = new Datatable();
ConfigStatement s = new ConfigStatement(ConfigStatementType.Text,
"select * from customers");
accessor.Fill(new FillParameter(
table3,
new Statement(s)));
try {
// load db-specific config and instantiate accessor
VanillaConfig config = VanillaConfig.CreateConfig(
Assembly.GetExecutingAssembly().GetManifestResourceStream
("VanillaTest.config.xml"),
"Data Source=(local);Initial Catalog=Northwind;Integrated Security=True");
// SqlServer: "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"
// SqlServer Express: "Data Source=(local)\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"
// Oracle: "Server=localhost;User ID=scott;Password=tiger"
// Access: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Program Files\\Microsoft Office\\OFFICE11\\SAMPLES\\Northwind.mdb"
IDBAccessor accessor = VanillaFactory.CreateDBAccessor(config);
// custom statement
NorthwindDataset northwindDataset = new NorthwindDataset();
accessor.Fill(new FillParameter(
northwindDataset.Customers,
new Statement("CustomersByCityAndMinOrderCount"),
new ParameterList(
new Parameter("city", "London"),
new Parameter("minordercount", 2)))
);
// insert data
NorthwindDataset.CustomersRow custIns = northwindDataset.Customers.NewCustomersRow();
custIns.CustomerID = "Foo";
custIns.CompanyName = "Foo";
custIns.City = "New York";
northwindDataset.Customers.AddCustomersRow(custIns);
try
{
accessor.Update(new UpdateParameter(northwindDataset.Customers));
}
catch (VanillaException e)
{
Console.WriteLine(e.Message);
}
// insert and delete data
NorthwindDataset.CustomersRow custDel = northwindDataset.Customers.NewCustomersRow();
custDel.CustomerID = "Foo2";
custDel.CompanyName = "Foo2";
custDel.City = "New York";
northwindDataset.Customers.AddCustomersRow(custDel);
try
{
accessor.Update(new UpdateParameter(northwindDataset.Customers));
custDel.Delete();
accessor.Update(new UpdateParameter(northwindDataset.Customers));
}
catch (VanillaException e)
{
Console.WriteLine(e.Message);
}
// custom statement preprocessed (due to user request)
northwindDataset.Customers.Clear();
ConfigStatement stmt = config.GetStatement("CustomersByCityAndMinOrderCount");
ConfigStatement stmt2 =
new ConfigStatement(stmt.StatementType, stmt.Code + " and 1=1", stmt.Parameters);
accessor.Fill(new FillParameter(
northwindDataset.Customers,
new Statement(stmt2),
new ParameterList(
new Parameter("city", "London"),
new Parameter("minordercount", 2)))
);
// generic statement, this means no sql statement is required (as dataset maps 1:1 to db)
// dataset without schema will receive schema information from db (all columns)
// FillParameter.SchemaHandling allows to apply different schema strategies
DataTable table1 = new DataTable();
accessor.Fill(new FillParameter(table1, "Customers"));
// invoke stored procedure
DataTable table2 = new DataTable();
accessor.Fill(new FillParameter(
table2,
new Statement("CustOrderHist"),
new ParameterList(new Parameter("customerid", "Foo"))));
// hardcoded custom statement (due to user request)
DataTable table3 = new DataTable();
ConfigStatement s = new ConfigStatement(ConfigStatementType.Text, "select * from customers");
accessor.Fill(new FillParameter(
table3,
new Statement(s)));
// simulate a concurrency issue
// fetch the same data twice
northwindDataset.Customers.Clear();
// sql code will be generated on-the-fly, based on the columsn defined in this typed dataset
accessor.Fill(new FillParameter(northwindDataset.Customers, new ParameterList(new Parameter("CustomerID", "Foo"))));
NorthwindDataset northwindDataset2 = new NorthwindDataset();
accessor.Fill(new FillParameter(northwindDataset2.Customers, new ParameterList(new Parameter("CustomerID", "Foo"))));
// write some changes back to db
foreach (NorthwindDataset.CustomersRow cust1 in northwindDataset.Customers)
{
cust1.City = "Paris";
}
UpdateParameter upd1 = new UpdateParameter(northwindDataset.Customers);
upd1.RefreshAfterUpdate = true;
upd1.Locking = UpdateParameter.LockingType.Optimistic;
accessor.Update(upd1);
// try to write some other changes back to db which are now based on wrong original values => concurrency excpetion
foreach (NorthwindDataset.CustomersRow cust in northwindDataset2.Customers) {
cust.City = "Berlin";
}
UpdateParameter upd2 = new UpdateParameter(northwindDataset2.Customers);
upd2.RefreshAfterUpdate = true;
upd2.Locking = UpdateParameter.LockingType.Optimistic;
try {
accessor.Update(upd2);
}
catch (VanillaConcurrencyException e) {
Console.WriteLine(e.Message);
}
// transaction example
northwindDataset.Customers.Clear();
NorthwindDataset.CustomersRow cust2 =
northwindDataset.Customers.NewCustomersRow();
cust2.CustomerID = "TEST1";
cust2.CompanyName = "Tester 1";
northwindDataset.Customers.AddCustomersRow(cust2);
TransactionTaskList list = new TransactionTaskList(
// generic update custom statement
new UpdateTransactionTask(
new UpdateParameter(northwindDataset.Customers)),
// custom statement
new ExecuteNonQueryTransactionTask(
new NonQueryParameter(new Statement("DeleteTestCustomers")))
);
accessor.ExecuteTransaction(list);
Console.WriteLine("VanillaTest completed successfully");
}
catch (VanillaException e) {
Console.WriteLine(e.Message);
}
Console.Write("Press to continue...");
Console.Read();
}
<generator class="identity" /><generator class="assigned" />